| 1344 | } activation_unlink_status_t; |
| 1345 | |
| 1346 | static activation_unlink_status_t activation_unlink_expected( |
| 1347 | const cbm_activation_transaction_t *transaction, const char *path, const char *name, |
| 1348 | const activation_file_identity_t *expected, bool allow_windows_deferred) { |
| 1349 | bool exists = false; |
| 1350 | if (!activation_path_matches(transaction, path, name, expected, &exists)) { |
| 1351 | return ACTIVATION_UNLINK_ERROR; |
| 1352 | } |
| 1353 | if (!exists) { |
| 1354 | return ACTIVATION_UNLINK_OK; |
| 1355 | } |
| 1356 | #ifdef _WIN32 |
| 1357 | wchar_t *wide = activation_utf8_to_wide(path); |
| 1358 | if (!wide) { |
| 1359 | return ACTIVATION_UNLINK_ERROR; |
| 1360 | } |
| 1361 | if (DeleteFileW(wide)) { |
| 1362 | free(wide); |
| 1363 | return ACTIVATION_UNLINK_OK; |
| 1364 | } |
| 1365 | DWORD error = GetLastError(); |
| 1366 | bool deferred = allow_windows_deferred && |
| 1367 | (error == ERROR_ACCESS_DENIED || error == ERROR_SHARING_VIOLATION || |
| 1368 | error == ERROR_LOCK_VIOLATION) && |
| 1369 | MoveFileExW(wide, NULL, MOVEFILE_DELAY_UNTIL_REBOOT) != 0; |
| 1370 | free(wide); |
| 1371 | return deferred ? ACTIVATION_UNLINK_DEFERRED : ACTIVATION_UNLINK_ERROR; |
| 1372 | #else |
| 1373 | (void)allow_windows_deferred; |
| 1374 | int result; |
| 1375 | do { |
| 1376 | result = unlinkat(transaction->directory_fd, name, 0); |
| 1377 | } while (result != 0 && errno == EINTR); |
| 1378 | return result == 0 || errno == ENOENT ? ACTIVATION_UNLINK_OK : ACTIVATION_UNLINK_ERROR; |
| 1379 | #endif |
| 1380 | } |
| 1381 | |
| 1382 | static void activation_transaction_destroy(cbm_activation_transaction_t *transaction) { |
| 1383 | if (!transaction) { |
no test coverage detected