Changeset 63794 in vbox
- Timestamp:
- Sep 12, 2016 11:29:34 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/VHD.cpp
r63785 r63794 258 258 static uint32_t vhdChecksum(void *pHeader, uint32_t cbSize) 259 259 { 260 uint32_t checksum = 0;260 uint32_t u32ChkSum = 0; 261 261 for (uint32_t i = 0; i < cbSize; i++) 262 checksum += ((unsigned char *)pHeader)[i];263 return ~ checksum;262 u32ChkSum += ((unsigned char *)pHeader)[i]; 263 return ~u32ChkSum; 264 264 } 265 265 … … 272 272 { 273 273 int rc; 274 PRTUTF16 tmp16 = NULL;274 PRTUTF16 pTmp16 = NULL; 275 275 size_t cTmp16Len; 276 276 277 rc = RTStrToUtf16(pszFilename, &tmp16); 278 if (RT_FAILURE(rc)) 279 goto out; 280 cTmp16Len = RTUtf16Len(tmp16); 281 if (cTmp16Len * sizeof(*tmp16) > cbBufSize) 282 { 283 rc = VERR_FILENAME_TOO_LONG; 284 goto out; 285 } 286 287 if (fBigEndian) 288 for (unsigned i = 0; i < cTmp16Len; i++) 289 pu16Buf[i] = RT_H2BE_U16(tmp16[i]); 290 else 291 memcpy(pu16Buf, tmp16, cTmp16Len * sizeof(*tmp16)); 292 if (pcbActualSize) 293 *pcbActualSize = (uint32_t)(cTmp16Len * sizeof(*tmp16)); 294 295 out: 296 if (tmp16) 297 RTUtf16Free(tmp16); 277 rc = RTStrToUtf16(pszFilename, &pTmp16); 278 if (RT_SUCCESS(rc)) 279 { 280 cTmp16Len = RTUtf16Len(pTmp16); 281 if (cTmp16Len * sizeof(*pTmp16) <= cbBufSize) 282 { 283 if (fBigEndian) 284 for (unsigned i = 0; i < cTmp16Len; i++) 285 pu16Buf[i] = RT_H2BE_U16(pTmp16[i]); 286 else 287 memcpy(pu16Buf, pTmp16, cTmp16Len * sizeof(*pTmp16)); 288 if (pcbActualSize) 289 *pcbActualSize = (uint32_t)(cTmp16Len * sizeof(*pTmp16)); 290 } 291 else 292 rc = VERR_FILENAME_TOO_LONG; 293 } 294 295 if (pTmp16) 296 RTUtf16Free(pTmp16); 298 297 return rc; 299 298 } … … 1113 1112 PCVDGEOMETRY pLCHSGeometry, PCRTUUID pUuid, 1114 1113 unsigned uOpenFlags, 1115 P FNVDPROGRESS pfnProgress, void *pvUser,1114 PVDINTERFACEPROGRESS pIfProgress, 1116 1115 unsigned uPercentStart, unsigned uPercentSpan) 1117 1116 { 1118 1117 RT_NOREF3(pszComment, pPCHSGeometry, pLCHSGeometry); 1119 int rc;1120 1118 VHDFooter Footer; 1121 1119 RTTIMESPEC now; … … 1123 1121 pImage->uOpenFlags = uOpenFlags; 1124 1122 pImage->uImageFlags = uImageFlags; 1125 1126 1123 pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk); 1127 1124 1128 rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, 1129 VDOpenFlagsToFileOpenFlags(uOpenFlags & ~VD_OPEN_FLAGS_READONLY, 1130 true /* fCreate */), 1131 &pImage->pStorage); 1132 if (RT_FAILURE(rc)) 1133 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VHD: cannot create image '%s'"), pImage->pszFilename); 1134 1135 1136 pImage->cbSize = cbSize; 1137 pImage->ImageUuid = *pUuid; 1138 RTUuidClear(&pImage->ParentUuid); 1139 vhdSetDiskGeometry(pImage, cbSize); 1140 1141 /* Initialize the footer. */ 1142 memset(&Footer, 0, sizeof(Footer)); 1143 memcpy(Footer.Cookie, VHD_FOOTER_COOKIE, sizeof(Footer.Cookie)); 1144 Footer.Features = RT_H2BE_U32(0x2); 1145 Footer.Version = RT_H2BE_U32(VHD_FOOTER_FILE_FORMAT_VERSION); 1146 Footer.Timestamp = RT_H2BE_U32(vhdRtTime2VhdTime(RTTimeNow(&now))); 1147 memcpy(Footer.CreatorApp, "vbox", sizeof(Footer.CreatorApp)); 1148 Footer.CreatorVer = RT_H2BE_U32(VBOX_VERSION); 1125 int rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, 1126 VDOpenFlagsToFileOpenFlags(uOpenFlags & ~VD_OPEN_FLAGS_READONLY, 1127 true /* fCreate */), 1128 &pImage->pStorage); 1129 if (RT_SUCCESS(rc)) 1130 { 1131 pImage->cbSize = cbSize; 1132 pImage->ImageUuid = *pUuid; 1133 RTUuidClear(&pImage->ParentUuid); 1134 vhdSetDiskGeometry(pImage, cbSize); 1135 1136 /* Initialize the footer. */ 1137 memset(&Footer, 0, sizeof(Footer)); 1138 memcpy(Footer.Cookie, VHD_FOOTER_COOKIE, sizeof(Footer.Cookie)); 1139 Footer.Features = RT_H2BE_U32(0x2); 1140 Footer.Version = RT_H2BE_U32(VHD_FOOTER_FILE_FORMAT_VERSION); 1141 Footer.Timestamp = RT_H2BE_U32(vhdRtTime2VhdTime(RTTimeNow(&now))); 1142 memcpy(Footer.CreatorApp, "vbox", sizeof(Footer.CreatorApp)); 1143 Footer.CreatorVer = RT_H2BE_U32(VBOX_VERSION); 1149 1144 #ifdef RT_OS_DARWIN 1150 Footer.CreatorOS = RT_H2BE_U32(0x4D616320); /* "Mac " */1145 Footer.CreatorOS = RT_H2BE_U32(0x4D616320); /* "Mac " */ 1151 1146 #else /* Virtual PC supports only two platforms atm, so everything else will be Wi2k. */ 1152 Footer.CreatorOS = RT_H2BE_U32(0x5769326B); /* "Wi2k" */1147 Footer.CreatorOS = RT_H2BE_U32(0x5769326B); /* "Wi2k" */ 1153 1148 #endif 1154 Footer.OrigSize = RT_H2BE_U64(cbSize); 1155 Footer.CurSize = Footer.OrigSize; 1156 Footer.DiskGeometryCylinder = RT_H2BE_U16(pImage->PCHSGeometry.cCylinders); 1157 Footer.DiskGeometryHeads = pImage->PCHSGeometry.cHeads; 1158 Footer.DiskGeometrySectors = pImage->PCHSGeometry.cSectors; 1159 memcpy(Footer.UniqueID, pImage->ImageUuid.au8, sizeof(Footer.UniqueID)); 1160 Footer.SavedState = 0; 1161 1162 if (uImageFlags & VD_IMAGE_FLAGS_FIXED) 1163 { 1164 Footer.DiskType = RT_H2BE_U32(VHD_FOOTER_DISK_TYPE_FIXED); 1165 /* 1166 * Initialize fixed image. 1167 * "The size of the entire file is the size of the hard disk in 1168 * the guest operating system plus the size of the footer." 1169 */ 1170 pImage->u64DataOffset = VHD_FOOTER_DATA_OFFSET_FIXED; 1171 pImage->uCurrentEndOfFile = cbSize; 1172 rc = vdIfIoIntFileSetAllocationSize(pImage->pIfIo, pImage->pStorage, pImage->uCurrentEndOfFile + sizeof(VHDFooter), 1173 0 /* fFlags */, pfnProgress, pvUser, uPercentStart, uPercentSpan); 1174 if (RT_FAILURE(rc)) 1175 { 1176 vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VHD: cannot set the file size for '%s'"), pImage->pszFilename); 1177 goto out; 1149 Footer.OrigSize = RT_H2BE_U64(cbSize); 1150 Footer.CurSize = Footer.OrigSize; 1151 Footer.DiskGeometryCylinder = RT_H2BE_U16(pImage->PCHSGeometry.cCylinders); 1152 Footer.DiskGeometryHeads = pImage->PCHSGeometry.cHeads; 1153 Footer.DiskGeometrySectors = pImage->PCHSGeometry.cSectors; 1154 memcpy(Footer.UniqueID, pImage->ImageUuid.au8, sizeof(Footer.UniqueID)); 1155 Footer.SavedState = 0; 1156 1157 if (uImageFlags & VD_IMAGE_FLAGS_FIXED) 1158 { 1159 Footer.DiskType = RT_H2BE_U32(VHD_FOOTER_DISK_TYPE_FIXED); 1160 /* 1161 * Initialize fixed image. 1162 * "The size of the entire file is the size of the hard disk in 1163 * the guest operating system plus the size of the footer." 1164 */ 1165 pImage->u64DataOffset = VHD_FOOTER_DATA_OFFSET_FIXED; 1166 pImage->uCurrentEndOfFile = cbSize; 1167 rc = vdIfIoIntFileSetAllocationSize(pImage->pIfIo, pImage->pStorage, pImage->uCurrentEndOfFile + sizeof(VHDFooter), 1168 0 /* fFlags */, pIfProgress->pfnProgress, pIfProgress->Core.pvUser, 1169 uPercentStart, uPercentSpan); 1170 if (RT_FAILURE(rc)) 1171 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VHD: cannot set the file size for '%s'"), pImage->pszFilename); 1172 } 1173 else 1174 { 1175 /* 1176 * Initialize dynamic image. 1177 * 1178 * The overall structure of dynamic disk is: 1179 * 1180 * [Copy of hard disk footer (512 bytes)] 1181 * [Dynamic disk header (1024 bytes)] 1182 * [BAT (Block Allocation Table)] 1183 * [Parent Locators] 1184 * [Data block 1] 1185 * [Data block 2] 1186 * ... 1187 * [Data block N] 1188 * [Hard disk footer (512 bytes)] 1189 */ 1190 Footer.DiskType = (uImageFlags & VD_IMAGE_FLAGS_DIFF) 1191 ? RT_H2BE_U32(VHD_FOOTER_DISK_TYPE_DIFFERENCING) 1192 : RT_H2BE_U32(VHD_FOOTER_DISK_TYPE_DYNAMIC); 1193 /* We are half way thorough with creation of image, let the caller know. */ 1194 vdIfProgress(pIfProgress, (uPercentStart + uPercentSpan) / 2); 1195 1196 rc = vhdCreateDynamicImage(pImage, cbSize); 1197 } 1198 1199 if (RT_SUCCESS(rc)) 1200 { 1201 /* Compute and update the footer checksum. */ 1202 Footer.DataOffset = RT_H2BE_U64(pImage->u64DataOffset); 1203 Footer.Checksum = 0; 1204 Footer.Checksum = RT_H2BE_U32(vhdChecksum(&Footer, sizeof(Footer))); 1205 1206 pImage->vhdFooterCopy = Footer; 1207 1208 /* Store the footer */ 1209 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, pImage->uCurrentEndOfFile, 1210 &Footer, sizeof(Footer)); 1211 if (RT_SUCCESS(rc)) 1212 { 1213 /* Dynamic images contain a copy of the footer at the very beginning of the file. */ 1214 if (!(uImageFlags & VD_IMAGE_FLAGS_FIXED)) 1215 { 1216 /* Write the copy of the footer. */ 1217 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 0, &Footer, sizeof(Footer)); 1218 if (RT_FAILURE(rc)) 1219 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VHD: cannot write a copy of footer to image '%s'"), pImage->pszFilename); 1220 } 1221 } 1222 else 1223 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VHD: cannot write footer to image '%s'"), pImage->pszFilename); 1178 1224 } 1179 1225 } 1180 1226 else 1181 { 1182 /* 1183 * Initialize dynamic image. 1184 * 1185 * The overall structure of dynamic disk is: 1186 * 1187 * [Copy of hard disk footer (512 bytes)] 1188 * [Dynamic disk header (1024 bytes)] 1189 * [BAT (Block Allocation Table)] 1190 * [Parent Locators] 1191 * [Data block 1] 1192 * [Data block 2] 1193 * ... 1194 * [Data block N] 1195 * [Hard disk footer (512 bytes)] 1196 */ 1197 Footer.DiskType = (uImageFlags & VD_IMAGE_FLAGS_DIFF) 1198 ? RT_H2BE_U32(VHD_FOOTER_DISK_TYPE_DIFFERENCING) 1199 : RT_H2BE_U32(VHD_FOOTER_DISK_TYPE_DYNAMIC); 1200 /* We are half way thorough with creation of image, let the caller know. */ 1201 if (pfnProgress) 1202 pfnProgress(pvUser, (uPercentStart + uPercentSpan) / 2); 1203 1204 rc = vhdCreateDynamicImage(pImage, cbSize); 1205 if (RT_FAILURE(rc)) 1206 goto out; 1207 } 1208 1209 Footer.DataOffset = RT_H2BE_U64(pImage->u64DataOffset); 1210 1211 /* Compute and update the footer checksum. */ 1212 Footer.Checksum = 0; 1213 Footer.Checksum = RT_H2BE_U32(vhdChecksum(&Footer, sizeof(Footer))); 1214 1215 pImage->vhdFooterCopy = Footer; 1216 1217 /* Store the footer */ 1218 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, pImage->uCurrentEndOfFile, 1219 &Footer, sizeof(Footer)); 1220 if (RT_FAILURE(rc)) 1221 { 1222 vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VHD: cannot write footer to image '%s'"), pImage->pszFilename); 1223 goto out; 1224 } 1225 1226 /* Dynamic images contain a copy of the footer at the very beginning of the file. */ 1227 if (!(uImageFlags & VD_IMAGE_FLAGS_FIXED)) 1228 { 1229 /* Write the copy of the footer. */ 1230 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 0, &Footer, sizeof(Footer)); 1231 if (RT_FAILURE(rc)) 1232 { 1233 vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VHD: cannot write a copy of footer to image '%s'"), pImage->pszFilename); 1234 goto out; 1235 } 1236 } 1237 1238 out: 1239 if (RT_SUCCESS(rc) && pfnProgress) 1240 pfnProgress(pvUser, uPercentStart + uPercentSpan); 1227 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VHD: cannot create image '%s'"), pImage->pszFilename); 1228 1229 if (RT_SUCCESS(rc)) 1230 vdIfProgress(pIfProgress, uPercentStart + uPercentSpan); 1241 1231 1242 1232 if (RT_FAILURE(rc)) … … 1252 1242 RT_NOREF1(pVDIfsDisk); 1253 1243 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage)); 1254 int rc;1255 1244 PVDIOSTORAGE pStorage; 1256 uint64_t cbFile;1257 VHDFooter vhdFooter;1258 1259 1245 PVDINTERFACEIOINT pIfIo = VDIfIoIntGet(pVDIfsImage); 1260 1246 AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER); 1261 1247 1262 rc = vdIfIoIntFileOpen(pIfIo, pszFilename, 1263 VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY, 1264 false /* fCreate */), 1265 &pStorage); 1266 if (RT_FAILURE(rc)) 1267 goto out; 1268 1269 rc = vdIfIoIntFileGetSize(pIfIo, pStorage, &cbFile); 1270 if (RT_FAILURE(rc)) 1271 { 1248 int rc = vdIfIoIntFileOpen(pIfIo, pszFilename, 1249 VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY, 1250 false /* fCreate */), 1251 &pStorage); 1252 if (RT_SUCCESS(rc)) 1253 { 1254 uint64_t cbFile; 1255 1256 rc = vdIfIoIntFileGetSize(pIfIo, pStorage, &cbFile); 1257 if ( RT_SUCCESS(rc) 1258 && cbFile >= sizeof(VHDFooter)) 1259 { 1260 VHDFooter vhdFooter; 1261 1262 rc = vdIfIoIntFileReadSync(pIfIo, pStorage, cbFile - sizeof(VHDFooter), 1263 &vhdFooter, sizeof(VHDFooter)); 1264 if (RT_SUCCESS(rc)) 1265 { 1266 if (memcmp(vhdFooter.Cookie, VHD_FOOTER_COOKIE, VHD_FOOTER_COOKIE_SIZE) != 0) 1267 { 1268 /* 1269 * There is also a backup header at the beginning in case the image got corrupted. 1270 * Such corrupted images are detected here to let the open handler repair it later. 1271 */ 1272 rc = vdIfIoIntFileReadSync(pIfIo, pStorage, 0, &vhdFooter, sizeof(VHDFooter)); 1273 if ( RT_FAILURE(rc) 1274 || (memcmp(vhdFooter.Cookie, VHD_FOOTER_COOKIE, VHD_FOOTER_COOKIE_SIZE) != 0)) 1275 rc = VERR_VD_VHD_INVALID_HEADER; 1276 } 1277 1278 if (RT_SUCCESS(rc)) 1279 *penmType = VDTYPE_HDD; 1280 } 1281 else 1282 rc = VERR_VD_VHD_INVALID_HEADER; 1283 } 1284 else if (RT_SUCCESS(rc)) 1285 rc = VERR_VD_VHD_INVALID_HEADER; 1286 1272 1287 vdIfIoIntFileClose(pIfIo, pStorage); 1273 rc = VERR_VD_VHD_INVALID_HEADER; 1274 goto out; 1275 } 1276 1277 rc = vdIfIoIntFileReadSync(pIfIo, pStorage, cbFile - sizeof(VHDFooter), 1278 &vhdFooter, sizeof(VHDFooter)); 1279 if (RT_SUCCESS(rc)) 1280 { 1281 if (memcmp(vhdFooter.Cookie, VHD_FOOTER_COOKIE, VHD_FOOTER_COOKIE_SIZE) != 0) 1282 { 1283 /* 1284 * There is also a backup header at the beginning in case the image got corrupted. 1285 * Such corrupted images are detected here to let the open handler repair it later. 1286 */ 1287 rc = vdIfIoIntFileReadSync(pIfIo, pStorage, 0, &vhdFooter, sizeof(VHDFooter)); 1288 if ( RT_FAILURE(rc) 1289 || (memcmp(vhdFooter.Cookie, VHD_FOOTER_COOKIE, VHD_FOOTER_COOKIE_SIZE) != 0)) 1290 rc = VERR_VD_VHD_INVALID_HEADER; 1291 } 1292 1293 if (RT_SUCCESS(rc)) 1294 *penmType = VDTYPE_HDD; 1295 } 1296 else 1297 rc = VERR_VD_VHD_INVALID_HEADER; 1298 1299 vdIfIoIntFileClose(pIfIo, pStorage); 1300 1301 out: 1288 } 1289 1302 1290 LogFlowFunc(("returns %Rrc\n", rc)); 1303 1291 return rc; … … 1309 1297 VDTYPE enmType, void **ppBackendData) 1310 1298 { 1311 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p enmType=%u ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, enmType, ppBackendData)); 1299 RT_NOREF1(enmType); /**< @todo r=klaus make use of the type info. */ 1300 1301 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p enmType=%u ppBackendData=%#p\n", 1302 pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, enmType, ppBackendData)); 1312 1303 int rc = VINF_SUCCESS; 1313 PVHDIMAGE pImage;1314 1315 NOREF(enmType); /**< @todo r=klaus make use of the type info. */1316 1304 1317 1305 /* Check open flags. All valid flags are supported. */ 1318 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK) 1319 { 1320 rc = VERR_INVALID_PARAMETER; 1321 goto out; 1322 } 1323 1324 /* Check remaining arguments. */ 1325 if ( !VALID_PTR(pszFilename) 1326 || !*pszFilename) 1327 { 1328 rc = VERR_INVALID_PARAMETER; 1329 goto out; 1330 } 1331 1332 pImage = (PVHDIMAGE)RTMemAllocZ(sizeof(VHDIMAGE)); 1333 if (!pImage) 1334 { 1306 AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER); 1307 AssertReturn((VALID_PTR(pszFilename) && *pszFilename), VERR_INVALID_PARAMETER); 1308 1309 PVHDIMAGE pImage = (PVHDIMAGE)RTMemAllocZ(sizeof(VHDIMAGE)); 1310 if (RT_LIKELY(pImage)) 1311 { 1312 pImage->pszFilename = pszFilename; 1313 pImage->pStorage = NULL; 1314 pImage->pVDIfsDisk = pVDIfsDisk; 1315 pImage->pVDIfsImage = pVDIfsImage; 1316 1317 rc = vhdOpenImage(pImage, uOpenFlags); 1318 if (RT_SUCCESS(rc)) 1319 *ppBackendData = pImage; 1320 else 1321 RTMemFree(pImage); 1322 } 1323 else 1335 1324 rc = VERR_NO_MEMORY; 1336 goto out; 1337 } 1338 1339 pImage->pszFilename = pszFilename; 1340 pImage->pStorage = NULL; 1341 pImage->pVDIfsDisk = pVDIfsDisk; 1342 pImage->pVDIfsImage = pVDIfsImage; 1343 1344 rc = vhdOpenImage(pImage, uOpenFlags); 1345 if (RT_SUCCESS(rc)) 1346 *ppBackendData = pImage; 1347 else 1348 RTMemFree(pImage); 1349 1350 out: 1325 1351 1326 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData)); 1352 1327 return rc; … … 1365 1340 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 enmType=%u ppBackendData=%#p", 1366 1341 pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, enmType, ppBackendData)); 1367 int rc = VINF_SUCCESS; 1368 PVHDIMAGE pImage; 1369 1370 PFNVDPROGRESS pfnProgress = NULL; 1371 void *pvUser = NULL; 1342 int rc; 1372 1343 PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation); 1373 if (pIfProgress)1374 {1375 pfnProgress = pIfProgress->pfnProgress;1376 pvUser = pIfProgress->Core.pvUser;1377 }1378 1344 1379 1345 /* Check the VD container type. */ 1380 1346 if (enmType != VDTYPE_HDD) 1381 { 1382 rc = VERR_VD_INVALID_TYPE; 1383 goto out; 1384 } 1347 return VERR_VD_INVALID_TYPE; 1385 1348 1386 1349 /* Check open flags. All valid flags are supported. */ 1387 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK) 1388 { 1389 rc = VERR_INVALID_PARAMETER; 1390 return rc; 1391 } 1392 1350 AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER); 1351 AssertReturn( VALID_PTR(pszFilename) 1352 && *pszFilename 1353 && VALID_PTR(pPCHSGeometry) 1354 && VALID_PTR(pLCHSGeometry), VERR_INVALID_PARAMETER); 1393 1355 /** @todo Check the values of other params */ 1394 1356 1395 pImage = (PVHDIMAGE)RTMemAllocZ(sizeof(VHDIMAGE)); 1396 if (!pImage) 1397 { 1357 PVHDIMAGE pImage = (PVHDIMAGE)RTMemAllocZ(sizeof(VHDIMAGE)); 1358 if (RT_LIKELY(pImage)) 1359 { 1360 pImage->pszFilename = pszFilename; 1361 pImage->pStorage = NULL; 1362 pImage->pVDIfsDisk = pVDIfsDisk; 1363 pImage->pVDIfsImage = pVDIfsImage; 1364 1365 /* Get I/O interface. */ 1366 pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage); 1367 if (RT_LIKELY(VALID_PTR(pImage->pIfIo))) 1368 { 1369 rc = vhdCreateImage(pImage, cbSize, uImageFlags, pszComment, 1370 pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, 1371 pIfProgress, uPercentStart, uPercentSpan); 1372 if (RT_SUCCESS(rc)) 1373 { 1374 /* So far the image is opened in read/write mode. Make sure the 1375 * image is opened in read-only mode if the caller requested that. */ 1376 if (uOpenFlags & VD_OPEN_FLAGS_READONLY) 1377 { 1378 vhdFreeImage(pImage, false); 1379 rc = vhdOpenImage(pImage, uOpenFlags); 1380 } 1381 1382 if (RT_SUCCESS(rc)) 1383 *ppBackendData = pImage; 1384 } 1385 } 1386 else 1387 rc = VERR_INVALID_PARAMETER; 1388 1389 if (RT_FAILURE(rc)) 1390 RTMemFree(pImage); 1391 } 1392 else 1398 1393 rc = VERR_NO_MEMORY; 1399 return rc; 1400 } 1401 pImage->pszFilename = pszFilename; 1402 pImage->pStorage = NULL; 1403 pImage->pVDIfsDisk = pVDIfsDisk; 1404 pImage->pVDIfsImage = pVDIfsImage; 1405 1406 /* Get I/O interface. */ 1407 pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage); 1408 if (RT_UNLIKELY(!VALID_PTR(pImage->pIfIo))) 1409 { 1410 RTMemFree(pImage); 1411 return VERR_INVALID_PARAMETER; 1412 } 1413 1414 rc = vhdCreateImage(pImage, cbSize, uImageFlags, pszComment, 1415 pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, 1416 pfnProgress, pvUser, uPercentStart, uPercentSpan); 1417 1418 if (RT_SUCCESS(rc)) 1419 { 1420 /* So far the image is opened in read/write mode. Make sure the 1421 * image is opened in read-only mode if the caller requested that. */ 1422 if (uOpenFlags & VD_OPEN_FLAGS_READONLY) 1423 { 1424 vhdFreeImage(pImage, false); 1425 rc = vhdOpenImage(pImage, uOpenFlags); 1426 if (RT_FAILURE(rc)) 1427 { 1428 RTMemFree(pImage); 1429 goto out; 1430 } 1431 } 1432 *ppBackendData = pImage; 1433 } 1434 else 1435 RTMemFree(pImage); 1436 1437 out: 1394 1438 1395 LogFlowFunc(("returns %Rrc\n", rc)); 1439 1396 return rc; … … 1448 1405 1449 1406 /* Check arguments. */ 1450 if ( !pImage 1451 || !pszFilename 1452 || !*pszFilename) 1453 { 1454 rc = VERR_INVALID_PARAMETER; 1455 goto out; 1456 } 1407 AssertReturn((pImage && pszFilename && *pszFilename), VERR_INVALID_PARAMETER); 1457 1408 1458 1409 /* Close the image. */ 1459 1410 rc = vhdFreeImage(pImage, false); 1460 if (RT_FAILURE(rc)) 1461 goto out; 1462 1463 /* Rename the file. */ 1464 rc = vdIfIoIntFileMove(pImage->pIfIo, pImage->pszFilename, pszFilename, 0); 1465 if (RT_FAILURE(rc)) 1466 { 1467 /* The move failed, try to reopen the original image. */ 1468 int rc2 = vhdOpenImage(pImage, pImage->uOpenFlags); 1469 if (RT_FAILURE(rc2)) 1470 rc = rc2; 1471 1472 goto out; 1473 } 1474 1475 /* Update pImage with the new information. */ 1476 pImage->pszFilename = pszFilename; 1477 1478 /* Open the old file with new name. */ 1479 rc = vhdOpenImage(pImage, pImage->uOpenFlags); 1480 if (RT_FAILURE(rc)) 1481 goto out; 1482 1483 out: 1411 if (RT_SUCCESS(rc)) 1412 { 1413 /* Rename the file. */ 1414 rc = vdIfIoIntFileMove(pImage->pIfIo, pImage->pszFilename, pszFilename, 0); 1415 if (RT_SUCCESS(rc)) 1416 { 1417 /* Update pImage with the new information. */ 1418 pImage->pszFilename = pszFilename; 1419 1420 /* Open the old file with new name. */ 1421 rc = vhdOpenImage(pImage, pImage->uOpenFlags); 1422 } 1423 else 1424 { 1425 /* The move failed, try to reopen the original image. */ 1426 int rc2 = vhdOpenImage(pImage, pImage->uOpenFlags); 1427 if (RT_FAILURE(rc2)) 1428 rc = rc2; 1429 } 1430 } 1431 1484 1432 LogFlowFunc(("returns %Rrc\n", rc)); 1485 1433 return rc; … … 1491 1439 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete)); 1492 1440 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1493 int rc; 1494 1495 rc = vhdFreeImage(pImage, fDelete); 1441 1442 int rc = vhdFreeImage(pImage, fDelete); 1496 1443 RTMemFree(pImage); 1497 1444 … … 1509 1456 LogFlowFunc(("pBackendData=%p uOffset=%#llx pIoCtx=%#p cbRead=%u pcbActuallyRead=%p\n", pBackendData, uOffset, pIoCtx, cbRead, pcbActuallyRead)); 1510 1457 1511 if (uOffset + cbRead > pImage->cbSize) 1512 return VERR_INVALID_PARAMETER; 1458 AssertPtr(pImage); 1459 Assert(uOffset % 512 == 0); 1460 Assert(cbRead % 512 == 0); 1461 AssertReturn((VALID_PTR(pIoCtx) && cbRead), VERR_INVALID_PARAMETER); 1462 AssertReturn(uOffset + cbRead <= pImage->cbSize, VERR_INVALID_PARAMETER); 1513 1463 1514 1464 /* … … 1628 1578 1629 1579 AssertPtr(pImage); 1630 Assert(uOffset % VHD_SECTOR_SIZE == 0); 1631 Assert(cbWrite % VHD_SECTOR_SIZE == 0); 1580 Assert(!(uOffset % VHD_SECTOR_SIZE)); 1581 Assert(!(cbWrite % VHD_SECTOR_SIZE)); 1582 AssertReturn((VALID_PTR(pIoCtx) && cbWrite), VERR_INVALID_PARAMETER); 1583 AssertReturn(uOffset + cbWrite <= pImage->cbSize, VERR_INVALID_PARAMETER); 1632 1584 1633 1585 if (pImage->pBlockAllocationTable) … … 1853 1805 static DECLCALLBACK(int) vhdFlush(void *pBackendData, PVDIOCTX pIoCtx) 1854 1806 { 1807 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1855 1808 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1856 1809 1857 1810 /* No need to write anything here. Data is always updated on a write. */ 1858 return vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage, pIoCtx, NULL, NULL); 1811 int rc = vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage, pIoCtx, NULL, NULL); 1812 LogFlowFunc(("returns %Rrc\n", rc)); 1813 return rc; 1859 1814 } 1860 1815 … … 1864 1819 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1865 1820 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1866 unsigned ver = 0; 1867 1868 AssertPtr(pImage); 1869 1870 if (pImage) 1871 ver = 1; /**< @todo use correct version */ 1872 1873 LogFlowFunc(("returns %u\n", ver)); 1874 return ver; 1821 1822 AssertPtrReturn(pImage, 0); 1823 1824 unsigned uVersion = 1; /**< @todo use correct version */ 1825 1826 LogFlowFunc(("returns %u\n", uVersion)); 1827 return uVersion; 1875 1828 } 1876 1829 … … 1882 1835 uint32_t cb = 0; 1883 1836 1884 AssertPtr (pImage);1885 1886 if (pImage )1887 cb = 512;1837 AssertPtrReturn(pImage, 0); 1838 1839 if (pImage->pStorage) 1840 cb = VHD_SECTOR_SIZE; 1888 1841 1889 1842 LogFlowFunc(("returns %zu\n", cb)); … … 1914 1867 uint64_t cb = 0; 1915 1868 1916 AssertPtr (pImage);1917 1918 if (pImage && pImage->pStorage)1869 AssertPtrReturn(pImage, 0); 1870 1871 if (pImage->pStorage) 1919 1872 cb = pImage->uCurrentEndOfFile + sizeof(VHDFooter); 1920 1873 … … 1928 1881 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); 1929 1882 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1930 int rc; 1931 1932 AssertPtr(pImage); 1933 1934 if (pImage) 1935 { 1936 if (pImage->PCHSGeometry.cCylinders) 1937 { 1938 *pPCHSGeometry = pImage->PCHSGeometry; 1939 rc = VINF_SUCCESS; 1940 } 1941 else 1942 rc = VERR_VD_GEOMETRY_NOT_SET; 1943 } 1883 int rc = VINF_SUCCESS; 1884 1885 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 1886 1887 if (pImage->PCHSGeometry.cCylinders) 1888 *pPCHSGeometry = pImage->PCHSGeometry; 1944 1889 else 1945 rc = VERR_VD_NOT_OPENED; 1946 1947 LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors)); 1890 rc = VERR_VD_GEOMETRY_NOT_SET; 1891 1892 LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->PCHSGeometry.cCylinders, 1893 pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors)); 1948 1894 return rc; 1949 1895 } … … 1952 1898 static DECLCALLBACK(int) vhdSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry) 1953 1899 { 1954 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 1955 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1956 int rc; 1957 1958 AssertPtr(pImage); 1959 1960 if (pImage) 1961 { 1962 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1963 { 1964 rc = VERR_VD_IMAGE_READ_ONLY; 1965 goto out; 1966 } 1967 1900 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", 1901 pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 1902 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1903 int rc = VINF_SUCCESS; 1904 1905 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 1906 1907 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1908 rc = VERR_VD_IMAGE_READ_ONLY; 1909 else 1968 1910 pImage->PCHSGeometry = *pPCHSGeometry; 1969 rc = VINF_SUCCESS; 1970 } 1971 else 1972 rc = VERR_VD_NOT_OPENED; 1973 1974 out: 1911 1975 1912 LogFlowFunc(("returns %Rrc\n", rc)); 1976 1913 return rc; … … 1980 1917 static DECLCALLBACK(int) vhdGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry) 1981 1918 { 1982 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 1983 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1984 int rc; 1985 1986 AssertPtr(pImage); 1987 1988 if (pImage) 1989 { 1990 if (pImage->LCHSGeometry.cCylinders) 1991 { 1992 *pLCHSGeometry = pImage->LCHSGeometry; 1993 rc = VINF_SUCCESS; 1994 } 1995 else 1996 rc = VERR_VD_GEOMETRY_NOT_SET; 1997 } 1919 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 1920 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1921 int rc = VINF_SUCCESS; 1922 1923 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 1924 1925 if (pImage->LCHSGeometry.cCylinders) 1926 *pLCHSGeometry = pImage->LCHSGeometry; 1998 1927 else 1999 rc = VERR_VD_NOT_OPENED; 2000 2001 LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors)); 1928 rc = VERR_VD_GEOMETRY_NOT_SET; 1929 1930 LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->LCHSGeometry.cCylinders, 1931 pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors)); 2002 1932 return rc; 2003 1933 } … … 2007 1937 { 2008 1938 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2009 int rc; 2010 2011 AssertPtr(pImage); 2012 2013 if (pImage) 2014 { 2015 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2016 { 2017 rc = VERR_VD_IMAGE_READ_ONLY; 2018 goto out; 2019 } 2020 1939 int rc = VINF_SUCCESS; 1940 1941 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 1942 1943 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1944 rc = VERR_VD_IMAGE_READ_ONLY; 1945 else 2021 1946 pImage->LCHSGeometry = *pLCHSGeometry; 2022 rc = VINF_SUCCESS; 2023 } 2024 else 2025 rc = VERR_VD_NOT_OPENED; 2026 2027 out: 1947 2028 1948 LogFlowFunc(("returns %Rrc\n", rc)); 2029 1949 return rc; … … 2035 1955 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2036 1956 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2037 unsigned uImageFlags; 2038 2039 AssertPtr(pImage); 2040 2041 if (pImage) 2042 uImageFlags = pImage->uImageFlags; 2043 else 2044 uImageFlags = 0; 2045 2046 LogFlowFunc(("returns %#x\n", uImageFlags)); 2047 return uImageFlags; 1957 1958 AssertPtrReturn(pImage, 0); 1959 1960 LogFlowFunc(("returns %#x\n", pImage->uImageFlags)); 1961 return pImage->uImageFlags; 2048 1962 } 2049 1963 … … 2053 1967 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2054 1968 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2055 unsigned uOpenFlags; 2056 2057 AssertPtr(pImage); 2058 2059 if (pImage) 2060 uOpenFlags = pImage->uOpenFlags; 2061 else 2062 uOpenFlags = 0; 2063 2064 LogFlowFunc(("returns %#x\n", uOpenFlags)); 2065 return uOpenFlags; 1969 1970 AssertPtrReturn(pImage, 0); 1971 1972 LogFlowFunc(("returns %#x\n", pImage->uOpenFlags)); 1973 return pImage->uOpenFlags; 2066 1974 } 2067 1975 … … 2071 1979 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 2072 1980 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2073 int rc ;1981 int rc = VINF_SUCCESS; 2074 1982 2075 1983 /* Image must be opened and the new flags must be valid. */ … … 2077 1985 | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE 2078 1986 | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS))) 2079 {2080 1987 rc = VERR_INVALID_PARAMETER; 2081 goto out; 2082 } 2083 2084 /* Implement this operation via reopening the image. */ 2085 rc = vhdFreeImage(pImage, false); 2086 if (RT_FAILURE(rc)) 2087 goto out; 2088 rc = vhdOpenImage(pImage, uOpenFlags); 2089 2090 out: 1988 else 1989 { 1990 /* Implement this operation via reopening the image. */ 1991 rc = vhdFreeImage(pImage, false); 1992 if (RT_SUCCESS(rc)) 1993 rc = vhdOpenImage(pImage, uOpenFlags); 1994 } 1995 2091 1996 LogFlowFunc(("returns %Rrc\n", rc)); 2092 1997 return rc; … … 2100 2005 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 2101 2006 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2007 2008 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2009 2010 LogFlowFunc(("returns %Rrc comment='%s'\n", VERR_NOT_SUPPORTED, pszComment)); 2011 return VERR_NOT_SUPPORTED; 2012 } 2013 2014 /** @interface_method_impl{VDIMAGEBACKEND,pfnSetComment} */ 2015 static DECLCALLBACK(int) vhdSetComment(void *pBackendData, const char *pszComment) 2016 { 2017 RT_NOREF1(pszComment); 2018 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 2019 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2020 2021 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2022 2102 2023 int rc; 2103 2104 AssertPtr(pImage); 2105 2106 if (pImage) 2024 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2025 rc = VERR_VD_IMAGE_READ_ONLY; 2026 else 2107 2027 rc = VERR_NOT_SUPPORTED; 2028 2029 LogFlowFunc(("returns %Rrc\n", rc)); 2030 return rc; 2031 } 2032 2033 /** @interface_method_impl{VDIMAGEBACKEND,pfnGetUuid} */ 2034 static DECLCALLBACK(int) vhdGetUuid(void *pBackendData, PRTUUID pUuid) 2035 { 2036 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2037 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2038 2039 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2040 2041 *pUuid = pImage->ImageUuid; 2042 2043 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VINF_SUCCESS, pUuid)); 2044 return VINF_SUCCESS; 2045 } 2046 2047 /** @interface_method_impl{VDIMAGEBACKEND,pfnSetUuid} */ 2048 static DECLCALLBACK(int) vhdSetUuid(void *pBackendData, PCRTUUID pUuid) 2049 { 2050 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2051 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2052 int rc = VINF_SUCCESS; 2053 2054 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2055 2056 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2057 { 2058 pImage->ImageUuid = *pUuid; 2059 /* Update the footer copy. It will get written to disk when the image is closed. */ 2060 memcpy(&pImage->vhdFooterCopy.UniqueID, pUuid, 16); 2061 /* Update checksum. */ 2062 pImage->vhdFooterCopy.Checksum = 0; 2063 pImage->vhdFooterCopy.Checksum = RT_H2BE_U32(vhdChecksum(&pImage->vhdFooterCopy, sizeof(VHDFooter))); 2064 2065 /* Need to update the dynamic disk header to update the disk footer copy at the beginning. */ 2066 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)) 2067 pImage->fDynHdrNeedsUpdate = true; 2068 } 2069 else 2070 rc = VERR_VD_IMAGE_READ_ONLY; 2071 2072 LogFlowFunc(("returns %Rrc\n", rc)); 2073 return rc; 2074 } 2075 2076 /** @interface_method_impl{VDIMAGEBACKEND,pfnGetModificationUuid} */ 2077 static DECLCALLBACK(int) vhdGetModificationUuid(void *pBackendData, PRTUUID pUuid) 2078 { 2079 RT_NOREF1(pUuid); 2080 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2081 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2082 2083 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2084 2085 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid)); 2086 return VERR_NOT_SUPPORTED; 2087 } 2088 2089 /** @interface_method_impl{VDIMAGEBACKEND,pfnSetModificationUuid} */ 2090 static DECLCALLBACK(int) vhdSetModificationUuid(void *pBackendData, PCRTUUID pUuid) 2091 { 2092 RT_NOREF1(pUuid); 2093 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2094 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2095 2096 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2097 2098 int rc; 2099 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2100 rc = VERR_VD_IMAGE_READ_ONLY; 2101 else 2102 rc = VERR_NOT_SUPPORTED; 2103 2104 LogFlowFunc(("returns %Rrc\n", rc)); 2105 return rc; 2106 } 2107 2108 /** @interface_method_impl{VDIMAGEBACKEND,pfnGetParentUuid} */ 2109 static DECLCALLBACK(int) vhdGetParentUuid(void *pBackendData, PRTUUID pUuid) 2110 { 2111 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2112 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2113 2114 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2115 2116 *pUuid = pImage->ParentUuid; 2117 2118 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VINF_SUCCESS, pUuid)); 2119 return VINF_SUCCESS; 2120 } 2121 2122 /** @interface_method_impl{VDIMAGEBACKEND,pfnSetParentUuid} */ 2123 static DECLCALLBACK(int) vhdSetParentUuid(void *pBackendData, PCRTUUID pUuid) 2124 { 2125 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2126 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2127 int rc = VINF_SUCCESS; 2128 2129 if (pImage && pImage->pStorage) 2130 { 2131 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)) 2132 { 2133 pImage->ParentUuid = *pUuid; 2134 pImage->fDynHdrNeedsUpdate = true; 2135 } 2136 else 2137 rc = VERR_VD_IMAGE_READ_ONLY; 2138 } 2108 2139 else 2109 2140 rc = VERR_VD_NOT_OPENED; 2110 2141 2111 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));2112 return rc;2113 }2114 2115 /** @interface_method_impl{VDIMAGEBACKEND,pfnSetComment} */2116 static DECLCALLBACK(int) vhdSetComment(void *pBackendData, const char *pszComment)2117 {2118 RT_NOREF1(pszComment);2119 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));2120 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;2121 int rc;2122 2123 AssertPtr(pImage);2124 2125 if (pImage)2126 {2127 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)2128 rc = VERR_VD_IMAGE_READ_ONLY;2129 else2130 rc = VERR_NOT_SUPPORTED;2131 }2132 else2133 rc = VERR_VD_NOT_OPENED;2134 2135 2142 LogFlowFunc(("returns %Rrc\n", rc)); 2136 2143 return rc; 2137 2144 } 2138 2145 2139 /** @interface_method_impl{VDIMAGEBACKEND,pfnGetUuid} */ 2140 static DECLCALLBACK(int) vhdGetUuid(void *pBackendData, PRTUUID pUuid) 2141 { 2142 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2143 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2144 int rc; 2145 2146 AssertPtr(pImage); 2147 2148 if (pImage) 2149 { 2150 *pUuid = pImage->ImageUuid; 2151 rc = VINF_SUCCESS; 2152 } 2153 else 2154 rc = VERR_VD_NOT_OPENED; 2155 2156 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2157 return rc; 2158 } 2159 2160 /** @interface_method_impl{VDIMAGEBACKEND,pfnSetUuid} */ 2161 static DECLCALLBACK(int) vhdSetUuid(void *pBackendData, PCRTUUID pUuid) 2162 { 2163 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2164 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2165 int rc; 2166 2167 AssertPtr(pImage); 2168 2169 if (pImage) 2170 { 2171 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2172 { 2173 pImage->ImageUuid = *pUuid; 2174 /* Update the footer copy. It will get written to disk when the image is closed. */ 2175 memcpy(&pImage->vhdFooterCopy.UniqueID, pUuid, 16); 2176 /* Update checksum. */ 2177 pImage->vhdFooterCopy.Checksum = 0; 2178 pImage->vhdFooterCopy.Checksum = RT_H2BE_U32(vhdChecksum(&pImage->vhdFooterCopy, sizeof(VHDFooter))); 2179 2180 /* Need to update the dynamic disk header to update the disk footer copy at the beginning. */ 2181 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)) 2182 pImage->fDynHdrNeedsUpdate = true; 2183 rc = VINF_SUCCESS; 2184 } 2185 else 2186 rc = VERR_VD_IMAGE_READ_ONLY; 2187 } 2188 else 2189 rc = VERR_VD_NOT_OPENED; 2190 2191 LogFlowFunc(("returns %Rrc\n", rc)); 2192 return rc; 2193 } 2194 2195 /** @interface_method_impl{VDIMAGEBACKEND,pfnGetModificationUuid} */ 2196 static DECLCALLBACK(int) vhdGetModificationUuid(void *pBackendData, PRTUUID pUuid) 2146 /** @interface_method_impl{VDIMAGEBACKEND,pfnGetParentModificationUuid} */ 2147 static DECLCALLBACK(int) vhdGetParentModificationUuid(void *pBackendData, PRTUUID pUuid) 2197 2148 { 2198 2149 RT_NOREF1(pUuid); 2199 2150 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2200 2151 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2201 int rc; 2202 2203 AssertPtr(pImage); 2204 2205 if (pImage) 2206 rc = VERR_NOT_SUPPORTED; 2207 else 2208 rc = VERR_VD_NOT_OPENED; 2209 2210 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2211 return rc; 2212 } 2213 2214 /** @interface_method_impl{VDIMAGEBACKEND,pfnSetModificationUuid} */ 2215 static DECLCALLBACK(int) vhdSetModificationUuid(void *pBackendData, PCRTUUID pUuid) 2152 2153 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2154 2155 LogFlowFunc(("returns %Rrc (%RTuuid)\n", VERR_NOT_SUPPORTED, pUuid)); 2156 return VERR_NOT_SUPPORTED; 2157 } 2158 2159 /** @interface_method_impl{VDIMAGEBACKEND,pfnSetParentModificationUuid} */ 2160 static DECLCALLBACK(int) vhdSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid) 2216 2161 { 2217 2162 RT_NOREF1(pUuid); 2218 2163 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2219 2164 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2165 2166 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2167 2220 2168 int rc; 2221 2222 AssertPtr(pImage); 2223 2224 if (pImage) 2225 { 2226 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2227 rc = VERR_NOT_SUPPORTED; 2228 else 2229 rc = VERR_VD_IMAGE_READ_ONLY; 2230 } 2169 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2170 rc = VERR_VD_IMAGE_READ_ONLY; 2231 2171 else 2232 rc = VERR_VD_NOT_OPENED;2233 2234 LogFlowFunc(("returns %Rrc\n", rc));2235 return rc;2236 }2237 2238 /** @interface_method_impl{VDIMAGEBACKEND,pfnGetParentUuid} */2239 static DECLCALLBACK(int) vhdGetParentUuid(void *pBackendData, PRTUUID pUuid)2240 {2241 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));2242 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;2243 int rc;2244 2245 AssertPtr(pImage);2246 2247 if (pImage)2248 {2249 *pUuid = pImage->ParentUuid;2250 rc = VINF_SUCCESS;2251 }2252 else2253 rc = VERR_VD_NOT_OPENED;2254 2255 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));2256 return rc;2257 }2258 2259 /** @interface_method_impl{VDIMAGEBACKEND,pfnSetParentUuid} */2260 static DECLCALLBACK(int) vhdSetParentUuid(void *pBackendData, PCRTUUID pUuid)2261 {2262 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));2263 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;2264 int rc = VINF_SUCCESS;2265 2266 AssertPtr(pImage);2267 2268 if (pImage && pImage->pStorage)2269 {2270 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED))2271 {2272 pImage->ParentUuid = *pUuid;2273 pImage->fDynHdrNeedsUpdate = true;2274 }2275 else2276 rc = VERR_VD_IMAGE_READ_ONLY;2277 }2278 else2279 rc = VERR_VD_NOT_OPENED;2280 2281 LogFlowFunc(("returns %Rrc\n", rc));2282 return rc;2283 }2284 2285 /** @interface_method_impl{VDIMAGEBACKEND,pfnGetParentModificationUuid} */2286 static DECLCALLBACK(int) vhdGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)2287 {2288 RT_NOREF1(pUuid);2289 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));2290 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;2291 int rc;2292 2293 AssertPtr(pImage);2294 2295 if (pImage)2296 2172 rc = VERR_NOT_SUPPORTED; 2297 else2298 rc = VERR_VD_NOT_OPENED;2299 2300 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));2301 return rc;2302 }2303 2304 /** @interface_method_impl{VDIMAGEBACKEND,pfnSetParentModificationUuid} */2305 static DECLCALLBACK(int) vhdSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)2306 {2307 RT_NOREF1(pUuid);2308 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));2309 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;2310 int rc;2311 2312 AssertPtr(pImage);2313 2314 if (pImage)2315 {2316 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))2317 rc = VERR_NOT_SUPPORTED;2318 else2319 rc = VERR_VD_IMAGE_READ_ONLY;2320 }2321 else2322 rc = VERR_VD_NOT_OPENED;2323 2173 2324 2174 LogFlowFunc(("returns %Rrc\n", rc)); … … 2331 2181 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2332 2182 2333 AssertPtr(pImage); 2334 if (pImage) 2335 { 2336 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%u\n", 2337 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 2338 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 2339 VHD_SECTOR_SIZE); 2340 vdIfErrorMessage(pImage->pIfError, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid); 2341 vdIfErrorMessage(pImage->pIfError, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid); 2342 } 2183 AssertPtrReturnVoid(pImage); 2184 vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%u\n", 2185 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 2186 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 2187 VHD_SECTOR_SIZE); 2188 vdIfErrorMessage(pImage->pIfError, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid); 2189 vdIfErrorMessage(pImage->pIfError, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid); 2343 2190 } 2344 2191 … … 2346 2193 static DECLCALLBACK(int) vhdGetTimestamp(void *pBackendData, PRTTIMESPEC pTimestamp) 2347 2194 { 2348 int rc = VINF_SUCCESS; 2349 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2350 2351 AssertPtr(pImage); 2352 2353 if (pImage) 2354 rc = vdIfIoIntFileGetModificationTime(pImage->pIfIo, pImage->pszFilename, pTimestamp); 2355 else 2356 rc = VERR_VD_NOT_OPENED; 2195 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2196 2197 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2198 2199 int rc = vdIfIoIntFileGetModificationTime(pImage->pIfIo, pImage->pszFilename, pTimestamp); 2357 2200 2358 2201 LogFlowFunc(("returns %Rrc\n", rc)); … … 2363 2206 static DECLCALLBACK(int) vhdGetParentTimestamp(void *pBackendData, PRTTIMESPEC pTimestamp) 2364 2207 { 2365 int rc = VINF_SUCCESS; 2366 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2367 2368 AssertPtr(pImage); 2369 2370 if (pImage) 2371 vhdTime2RtTime(pTimestamp, pImage->u32ParentTimestamp); 2372 else 2373 rc = VERR_VD_NOT_OPENED; 2374 2375 LogFlowFunc(("returns %Rrc\n", rc)); 2376 return rc; 2208 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2209 2210 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2211 2212 vhdTime2RtTime(pTimestamp, pImage->u32ParentTimestamp); 2213 LogFlowFunc(("returns %Rrc\n", VINF_SUCCESS)); 2214 return VINF_SUCCESS; 2377 2215 } 2378 2216 … … 2383 2221 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2384 2222 2385 AssertPtr(pImage); 2386 if (pImage) 2387 { 2388 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2389 rc = VERR_VD_IMAGE_READ_ONLY; 2390 else 2391 { 2392 pImage->u32ParentTimestamp = vhdRtTime2VhdTime(pTimestamp); 2393 pImage->fDynHdrNeedsUpdate = true; 2394 } 2395 } 2223 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2224 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2225 rc = VERR_VD_IMAGE_READ_ONLY; 2396 2226 else 2397 rc = VERR_VD_NOT_OPENED; 2227 { 2228 pImage->u32ParentTimestamp = vhdRtTime2VhdTime(pTimestamp); 2229 pImage->fDynHdrNeedsUpdate = true; 2230 } 2398 2231 2399 2232 LogFlowFunc(("returns %Rrc\n", rc)); … … 2404 2237 static DECLCALLBACK(int) vhdGetParentFilename(void *pBackendData, char **ppszParentFilename) 2405 2238 { 2406 int rc = VINF_SUCCESS; 2407 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2408 2409 AssertPtr(pImage); 2410 if (pImage) 2411 *ppszParentFilename = RTStrDup(pImage->pszParentFilename); 2412 else 2413 rc = VERR_VD_NOT_OPENED; 2414 2415 LogFlowFunc(("returns %Rrc\n", rc)); 2416 return rc; 2239 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2240 2241 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2242 *ppszParentFilename = RTStrDup(pImage->pszParentFilename); 2243 2244 LogFlowFunc(("returns %Rrc\n", VINF_SUCCESS)); 2245 return VINF_SUCCESS; 2417 2246 } 2418 2247 … … 2423 2252 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2424 2253 2425 AssertPtr(pImage); 2426 if (pImage) 2427 { 2428 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2429 rc = VERR_VD_IMAGE_READ_ONLY; 2254 AssertPtrReturn(pImage, VERR_VD_NOT_OPENED); 2255 2256 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2257 rc = VERR_VD_IMAGE_READ_ONLY; 2258 else 2259 { 2260 if (pImage->pszParentFilename) 2261 RTStrFree(pImage->pszParentFilename); 2262 pImage->pszParentFilename = RTStrDup(pszParentFilename); 2263 if (!pImage->pszParentFilename) 2264 rc = VERR_NO_MEMORY; 2430 2265 else 2431 { 2432 if (pImage->pszParentFilename) 2433 RTStrFree(pImage->pszParentFilename); 2434 pImage->pszParentFilename = RTStrDup(pszParentFilename); 2435 if (!pImage->pszParentFilename) 2436 rc = VERR_NO_MEMORY; 2437 else 2438 pImage->fDynHdrNeedsUpdate = true; 2439 } 2440 } 2441 else 2442 rc = VERR_VD_NOT_OPENED; 2266 pImage->fDynHdrNeedsUpdate = true; 2267 } 2443 2268 2444 2269 LogFlowFunc(("returns %Rrc\n", rc)); … … 2456 2281 void *pvBuf = NULL; 2457 2282 uint32_t *paBlocks = NULL; 2283 PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation); 2458 2284 2459 2285 DECLCALLBACKMEMBER(int, pfnParentRead)(void *, uint64_t, void *, size_t) = NULL; … … 2464 2290 pfnParentRead = pIfParentState->pfnParentRead; 2465 2291 pvParent = pIfParentState->Core.pvUser; 2466 }2467 2468 PFNVDPROGRESS pfnProgress = NULL;2469 void *pvUser = NULL;2470 PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation);2471 if (pIfProgress)2472 {2473 pfnProgress = pIfProgress->pfnProgress;2474 pvUser = pIfProgress->Core.pvUser;2475 2292 } 2476 2293 … … 2583 2400 } 2584 2401 2585 if (pIfProgress && pIfProgress->pfnProgress) 2586 { 2587 rc = pIfProgress->pfnProgress(pIfProgress->Core.pvUser, 2588 (uint64_t)i * uPercentSpan / (cBlocks + cBlocksToMove) + uPercentStart); 2589 if (RT_FAILURE(rc)) 2590 break; 2591 } 2402 vdIfProgress(pIfProgress, (uint64_t)i * uPercentSpan / (cBlocks + cBlocksToMove) + uPercentStart); 2592 2403 } 2593 2404 … … 2654 2465 } 2655 2466 2656 if (pIfProgress && pIfProgress->pfnProgress) 2657 { 2658 rc = pIfProgress->pfnProgress(pIfProgress->Core.pvUser, 2659 (uint64_t)(cBlocks + cBlocksMoved) * uPercentSpan / (cBlocks + cBlocksToMove) + uPercentStart); 2660 2661 if (RT_FAILURE(rc)) 2662 break; 2663 } 2467 rc = vdIfProgress(pIfProgress, (uint64_t)(cBlocks + cBlocksMoved) * uPercentSpan / (cBlocks + cBlocksToMove) + uPercentStart); 2664 2468 } 2665 2469 } … … 2676 2480 RTMemTmpFree(pvBuf); 2677 2481 2678 if (RT_SUCCESS(rc) && pIfProgress && pIfProgress->pfnProgress) 2679 { 2680 pIfProgress->pfnProgress(pIfProgress->Core.pvUser, 2681 uPercentStart + uPercentSpan); 2682 } 2482 if (RT_SUCCESS(rc)) 2483 vdIfProgress(pIfProgress, uPercentStart + uPercentSpan); 2683 2484 2684 2485 LogFlowFunc(("returns %Rrc\n", rc)); … … 2693 2494 PVDINTERFACE pVDIfsOperation) 2694 2495 { 2695 RT_NOREF 4(uPercentSpan, uPercentStart, pVDIfsDisk, pVDIfsImage);2496 RT_NOREF5(uPercentSpan, uPercentStart, pVDIfsDisk, pVDIfsImage, pVDIfsOperation); 2696 2497 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2697 2498 int rc = VINF_SUCCESS; 2698 2699 PFNVDPROGRESS pfnProgress = NULL;2700 void *pvUser = NULL;2701 PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation);2702 if (pIfProgress)2703 {2704 pfnProgress = pIfProgress->pfnProgress;2705 pvUser = pIfProgress->Core.pvUser;2706 }2707 2499 2708 2500 /* Making the image smaller is not supported at the moment. */
Note:
See TracChangeset
for help on using the changeset viewer.