mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-25 18:40:19 -04:00
Delete snapshot links in Windows
This commit is contained in:
parent
7cab73bbb9
commit
6cd0b85f39
6 changed files with 90 additions and 28 deletions
|
|
@ -2445,7 +2445,20 @@ static int windows_rebuild_link(const struct fssnapshot_struct* fss, const char*
|
|||
return 0;
|
||||
}
|
||||
|
||||
int fssnapshot(const char* dir, struct fssnapshot_struct* fss)
|
||||
static int windows_delete_link(const struct fssnapshot_struct* fss, const char* name)
|
||||
{
|
||||
char link_path[PATH_MAX];
|
||||
|
||||
pathcpy(link_path, sizeof(link_path), fss->snapshot_dir);
|
||||
pathcat(link_path, sizeof(link_path), name);
|
||||
|
||||
/* remove link if present */
|
||||
windows_rmdir(link_path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fssnapshot_mount(const char* dir, struct fssnapshot_struct* fss)
|
||||
{
|
||||
wchar_t conv_buf_vol[CONV_MAX];
|
||||
char conv_buf_root[CONV_MAX];
|
||||
|
|
@ -2537,6 +2550,7 @@ int fssnapshot_stat(struct fssnapshot_struct* fss, const char* name, struct stat
|
|||
|
||||
pathcpy(link_path, sizeof(link_path), fss->snapshot_dir);
|
||||
pathcat(link_path, sizeof(link_path), name);
|
||||
pathcat(link_path, sizeof(link_path), SNAPSHOT_GUID); /* we check the GUID as it's the one that matter */
|
||||
|
||||
/* use lstat because we want to check the link */
|
||||
if (windows_lstat(link_path, st) != 0)
|
||||
|
|
@ -2600,6 +2614,9 @@ int fssnapshot_create(const struct fssnapshot_struct* fss, const char* name)
|
|||
pathcpy(link_path, sizeof(link_path), fss->snapshot_dir);
|
||||
pathcat(link_path, sizeof(link_path), name);
|
||||
|
||||
/* remove potential stale link */
|
||||
windows_rmdir(link_path);
|
||||
|
||||
int ret = windows_symlink_directory(target_path, link_path);
|
||||
if (ret != 0) {
|
||||
log_error(errno, "Error creating symlink '%s'. %s.\n", link_path, strerror(errno));
|
||||
|
|
@ -2629,7 +2646,6 @@ bail_and_delete:
|
|||
|
||||
int fssnapshot_delete(const struct fssnapshot_struct* fss, const char* name)
|
||||
{
|
||||
char link_path[PATH_MAX];
|
||||
char guid[PATH_MAX];
|
||||
char cmd[PS_CMD_MAX];
|
||||
char guid_link[PATH_MAX];
|
||||
|
|
@ -2638,16 +2654,13 @@ int fssnapshot_delete(const struct fssnapshot_struct* fss, const char* name)
|
|||
pathcat(guid_link, sizeof(guid_link), name);
|
||||
pathcat(guid_link, sizeof(guid_link), SNAPSHOT_GUID);
|
||||
|
||||
pathcpy(link_path, sizeof(link_path), fss->snapshot_dir);
|
||||
pathcat(link_path, sizeof(link_path), name);
|
||||
|
||||
if (windows_read_guid(guid_link, guid, sizeof(guid)) != 0)
|
||||
return -1;
|
||||
|
||||
/* if the GUID link is gone, assume everything is gone */
|
||||
if (guid[0] == 0) {
|
||||
/* remove as not valid anymore */
|
||||
windows_rmdir(link_path);
|
||||
windows_delete_link(fss, name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2657,12 +2670,12 @@ int fssnapshot_delete(const struct fssnapshot_struct* fss, const char* name)
|
|||
if (ret != 0) {
|
||||
log_error(errno, "Error destroy the snapshot from GUID '%s'. %s.\n", guid, strerror(errno));
|
||||
/* remove as not valid anymore */
|
||||
windows_rmdir(link_path);
|
||||
windows_delete_link(fss, name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* remove live symlink if present */
|
||||
windows_rmdir(link_path);
|
||||
windows_delete_link(fss, name);
|
||||
|
||||
/* remove persistent GUID symlink */
|
||||
if (windows_rmdir(guid_link) != 0) {
|
||||
|
|
@ -2675,16 +2688,9 @@ int fssnapshot_delete(const struct fssnapshot_struct* fss, const char* name)
|
|||
|
||||
int fssnapshot_rename(const struct fssnapshot_struct* fss, const char* old_name, const char* new_name)
|
||||
{
|
||||
char old_link[PATH_MAX];
|
||||
char new_link[PATH_MAX];
|
||||
char old_guid[PATH_MAX];
|
||||
char new_guid[PATH_MAX];
|
||||
|
||||
pathcpy(old_link, sizeof(old_link), fss->snapshot_dir);
|
||||
pathcat(old_link, sizeof(old_link), old_name);
|
||||
pathcpy(new_link, sizeof(new_link), fss->snapshot_dir);
|
||||
pathcat(new_link, sizeof(new_link), new_name);
|
||||
|
||||
pathcpy(old_guid, sizeof(old_guid), fss->snapshot_dir);
|
||||
pathcat(old_guid, sizeof(old_guid), old_name);
|
||||
pathcat(old_guid, sizeof(old_guid), SNAPSHOT_GUID);
|
||||
|
|
@ -2692,21 +2698,33 @@ int fssnapshot_rename(const struct fssnapshot_struct* fss, const char* old_name,
|
|||
pathcat(new_guid, sizeof(new_guid), new_name);
|
||||
pathcat(new_guid, sizeof(new_guid), SNAPSHOT_GUID);
|
||||
|
||||
if (windows_rename(old_link, new_link) != 0) {
|
||||
log_error(errno, "Error renaming '%s' to '%s'. %s.\n", old_link, new_link, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (windows_rename(old_guid, new_guid) != 0) {
|
||||
log_error(errno, "Error renaming '%s' to '%s'. %s.\n", old_guid, new_guid, strerror(errno));
|
||||
/* try to restore */
|
||||
windows_rename(new_link, old_link);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* the rename is the latest operation, and then we don't care about the links, we just remove both */
|
||||
windows_delete_link(fss, old_name);
|
||||
windows_delete_link(fss, new_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fssnapshot_unmount(const struct fssnapshot_struct* fss)
|
||||
{
|
||||
/*
|
||||
* Remove symlinks on exit to prevent "Dangling Links."
|
||||
* Since \Device\HarddiskVolumeShadowCopyN paths are reassigned by the kernel
|
||||
* at boot, a stale link would either point to a non-existent device or,
|
||||
* worse, a different disk's snapshot.
|
||||
*
|
||||
* Deleting the link ensures system hygiene and prevents users from seeing
|
||||
* "Location not available" errors or incorrect data after a reboot.
|
||||
*/
|
||||
windows_delete_link(fss, SNAPSHOT_PENDING);
|
||||
windows_delete_link(fss, SNAPSHOT_STABLE);
|
||||
}
|
||||
|
||||
uint64_t os_tick(void)
|
||||
{
|
||||
LARGE_INTEGER t;
|
||||
|
|
|
|||
|
|
@ -426,7 +426,16 @@ struct fssnapshot_struct {
|
|||
* @param fss Output snapshot context
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int fssnapshot(const char* dir, struct fssnapshot_struct* fss);
|
||||
int fssnapshot_mount(const char* dir, struct fssnapshot_struct* fss);
|
||||
|
||||
/**
|
||||
* Unmount the snapshots.
|
||||
*
|
||||
* Required in Windows to remove the temporary symlinks.
|
||||
*
|
||||
* @param fss Snapshot context
|
||||
*/
|
||||
void fssnapshot_unmount(const struct fssnapshot_struct* fss);
|
||||
|
||||
/**
|
||||
* Stat the snapshot directory.
|
||||
|
|
|
|||
|
|
@ -1856,8 +1856,10 @@ int snapraid_main(int argc, char* argv[])
|
|||
ret = state_sync(&state, blockstart, blockcount);
|
||||
|
||||
/* commit the snapshot as stable */
|
||||
if (ret == 0)
|
||||
if (ret == 0) {
|
||||
state_snapshot_commit(&state);
|
||||
state_snapshot_cleanup(&state);
|
||||
}
|
||||
} else if (operation == OPERATION_DRY) {
|
||||
state_read(&state);
|
||||
|
||||
|
|
@ -1899,6 +1901,10 @@ int snapraid_main(int argc, char* argv[])
|
|||
state_snapshot_read(&state);
|
||||
|
||||
ret = state_scrub(&state, plan100, olderthan);
|
||||
|
||||
if (ret == 0) {
|
||||
state_snapshot_cleanup(&state);
|
||||
}
|
||||
} else if (operation == OPERATION_REWRITE) {
|
||||
state_read(&state);
|
||||
|
||||
|
|
@ -2023,6 +2029,10 @@ int snapraid_main(int argc, char* argv[])
|
|||
if (opt.gui_rescan_after)
|
||||
state_scan(&state);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
state_snapshot_cleanup(&state);
|
||||
}
|
||||
} else {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(errno, "Unexpected command '%s'\n", command);
|
||||
|
|
|
|||
|
|
@ -5834,7 +5834,7 @@ int state_snapshot_new(struct snapraid_state* state)
|
|||
struct snapraid_disk* disk = i->data;
|
||||
|
||||
/* check if it supports snapshot */
|
||||
if (fssnapshot(disk->mount_point, &disk->fss) != 0)
|
||||
if (fssnapshot_mount(disk->mount_point, &disk->fss) != 0)
|
||||
continue;
|
||||
|
||||
size_t root_len = strlen(disk->fss.root_dir);
|
||||
|
|
@ -5906,7 +5906,7 @@ void state_snapshot_read(struct snapraid_state* state)
|
|||
struct snapraid_disk* disk = i->data;
|
||||
|
||||
/* check if it supports snapshot */
|
||||
if (fssnapshot(disk->mount_point, &disk->fss) != 0)
|
||||
if (fssnapshot_mount(disk->mount_point, &disk->fss) != 0)
|
||||
continue;
|
||||
|
||||
size_t root_len = strlen(disk->fss.root_dir);
|
||||
|
|
@ -5939,7 +5939,7 @@ void state_snapshot_write(struct snapraid_state* state, tommy_list* filterlist_d
|
|||
struct snapraid_disk* disk = i->data;
|
||||
|
||||
/* check if it supports snapshot */
|
||||
if (fssnapshot(disk->mount_point, &disk->fss) != 0)
|
||||
if (fssnapshot_mount(disk->mount_point, &disk->fss) != 0)
|
||||
continue;
|
||||
|
||||
size_t root_len = strlen(disk->fss.root_dir);
|
||||
|
|
@ -5979,3 +5979,16 @@ void state_snapshot_write(struct snapraid_state* state, tommy_list* filterlist_d
|
|||
}
|
||||
}
|
||||
|
||||
void state_snapshot_cleanup(struct snapraid_state* state)
|
||||
{
|
||||
for (tommy_node* i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
|
||||
/* check if it supports snapshot */
|
||||
if (disk->fss.magic == 0)
|
||||
continue;
|
||||
|
||||
fssnapshot_unmount(&disk->fss);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -445,6 +445,13 @@ void state_snapshot_read(struct snapraid_state* state);
|
|||
*/
|
||||
void state_snapshot_write(struct snapraid_state* state, tommy_list* filterlist_disk);
|
||||
|
||||
/**
|
||||
* Cleanup snapshots
|
||||
*
|
||||
* Required only in Windows.
|
||||
*/
|
||||
void state_snapshot_cleanup(struct snapraid_state* state);
|
||||
|
||||
/****************************************************************************/
|
||||
/* misc */
|
||||
|
||||
|
|
|
|||
|
|
@ -2558,7 +2558,7 @@ static int fssnapshot_zfs(const char* dir, uint32_t magic, struct fssnapshot_str
|
|||
}
|
||||
#endif
|
||||
|
||||
int fssnapshot(const char* path, struct fssnapshot_struct* fss)
|
||||
int fssnapshot_mount(const char* path, struct fssnapshot_struct* fss)
|
||||
{
|
||||
#if HAVE_LINUX_DEVICE
|
||||
struct statfs sfs;
|
||||
|
|
@ -3069,6 +3069,11 @@ int fssnapshot_rename(const struct fssnapshot_struct* fss, const char* old_name,
|
|||
#endif
|
||||
}
|
||||
|
||||
void fssnapshot_unmount(const struct fssnapshot_struct* fss)
|
||||
{
|
||||
(void)fss;
|
||||
}
|
||||
|
||||
uint64_t os_tick(void)
|
||||
{
|
||||
#if HAVE_MACH_ABSOLUTE_TIME
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue