Skip to content

Commit

Permalink
Treat deduplicated reparse points correctly
Browse files Browse the repository at this point in the history
IO_REPARSE_TAG_DEDUP reparse points were treated like symlinks before.
We now understand these reparese points and treat them like normal
files, which is called

"Nonoptimized Backup and Restore of Data Deduplication-Enabled Volumes"

This means the files are treated like normal files and not like reparse
points.

Files on deduplicated volumes can be backed up and restored like files
on any other windows filesystem.

For more details see:

https://msdn.microsoft.com/en-us/library/hh769304%28v=vs.85%29.aspx

Fixes #467: Error in restoring deduplicated files
  • Loading branch information
pstorz authored and Marco van Wieringen committed May 21, 2015
1 parent 905ed4d commit 7804e55
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 14 deletions.
15 changes: 12 additions & 3 deletions src/findlib/attribs.c
Expand Up @@ -554,8 +554,10 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)

unix_name_to_win32(&ff_pkt->sys_fname, ff_pkt->fname);

/** try unicode version */
if (p_GetFileAttributesExW) {
/**
* Try unicode version
*/
POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
make_win32_path_UTF8_2_wchar(&pwszBuf, ff_pkt->fname);

Expand All @@ -567,8 +569,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
win_error(jcr, "GetFileAttributesExW:", ff_pkt->sys_fname);
return STREAM_UNIX_ATTRIBUTES;
}
}
else {
} else {
if (!p_GetFileAttributesExA)
return STREAM_UNIX_ATTRIBUTES;

Expand All @@ -579,6 +580,13 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
}
}

/*
* Instead of using the current dwFileAttributes use the
* ff_pkt->statp.st_rdev which contains the actual fileattributes we
* want to save for this file.
*/
atts.dwFileAttributes = ff_pkt->statp.st_rdev;

p += to_base64((uint64_t)atts.dwFileAttributes, p);
*p++ = ' '; /* separate fields with a space */
li.LowPart = atts.ftCreationTime.dwLowDateTime;
Expand All @@ -597,6 +605,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
*p++ = ' ';
p += to_base64((uint64_t)atts.nFileSizeLow, p);
*p = 0;

return STREAM_UNIX_ATTRIBUTES_EX;
}

Expand Down
49 changes: 38 additions & 11 deletions src/win32/compat/compat.c
Expand Up @@ -1294,13 +1294,12 @@ static int get_windows_file_info(const char *filename, struct stat *sb, bool is_
* We store the full windows file attributes into st_rdev.
*/
sb->st_rdev = *pdwFileAttributes;
if ((*pdwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
(*pdwReserved0 & IO_REPARSE_TAG_DEDUP)) {
sb->st_rdev |= FILE_ATTRIBUTES_DEDUPED_ITEM;
}
}

if (is_directory) {
/*
* Directory
*/
sb->st_mode |= S_IFDIR;

/*
Expand All @@ -1314,7 +1313,8 @@ static int get_windows_file_info(const char *filename, struct stat *sb, bool is_
* so it is like a Unix mount point (change of filesystem).
*/
if ((*pdwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
if (*pdwReserved0 == IO_REPARSE_TAG_MOUNT_POINT) {
switch (*pdwReserved0) {
case IO_REPARSE_TAG_MOUNT_POINT: {
/*
* A mount point can be:
* Volume Mount Point "\\??\\volume{..."
Expand All @@ -1333,7 +1333,9 @@ static int get_windows_file_info(const char *filename, struct stat *sb, bool is_
}
}
free_pool_memory(vmp);
} else if (*pdwReserved0 == IO_REPARSE_TAG_SYMLINK) {
break;
}
case IO_REPARSE_TAG_SYMLINK: {
POOLMEM *slt;

Dmsg0(dbglvl, "We have a symlinked directory!\n");
Expand All @@ -1348,21 +1350,43 @@ static int get_windows_file_info(const char *filename, struct stat *sb, bool is_
Dmsg2(dbglvl, "Symlinked Directory %s points to: %s\n", filename, slt);
}
free_pool_memory(slt);
} else {
Dmsg0(dbglvl, "IO_REPARSE_TAG_MOUNT_POINT with unhandled IO_REPARSE_TAG\n");
break;
}
default:
Dmsg1(dbglvl, "IO_REPARSE_TAG_MOUNT_POINT with unhandled IO_REPARSE_TAG %d\n", *pdwReserved0);
break;
}
}
} else { /* no directory */
} else {
/*
* No directory
*/
if ((*pdwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
if (*pdwReserved0 & IO_REPARSE_TAG_SYMLINK) {
switch (*pdwReserved0) {
case IO_REPARSE_TAG_SYMLINK: {
POOLMEM *slt = get_pool_memory(PM_NAME);

Dmsg0(dbglvl, "We have a symlinked file!\n");
sb->st_mode |= S_IFLNK;

POOLMEM *slt = get_pool_memory(PM_NAME);
if (get_symlink_data(filename, &slt)) {
Dmsg2(dbglvl, "Symlinked File %s points to: %s\n", filename, slt);
}
free_pool_memory(slt);
break;
}
case IO_REPARSE_TAG_DEDUP:
Dmsg0(dbglvl, "We have a deduplicated file!\n");
sb->st_rdev |= FILE_ATTRIBUTES_DEDUPED_ITEM;

/*
* We treat a deduped file as a normal file.
*/
sb->st_mode |= S_IFREG;
break;
default:
Dmsg1(dbglvl, "IO_REPARSE_TAG_MOUNT_POINT with unhandled IO_REPARSE_TAG %d\n", *pdwReserved0);
break;
}
}
}
Expand Down Expand Up @@ -2669,6 +2693,9 @@ bool win32_restore_file_attributes(POOLMEM *ofname, HANDLE handle, WIN32_FILE_AT
}

if (handle != INVALID_HANDLE_VALUE) {
if (atts->dwFileAttributes & FILE_ATTRIBUTES_DEDUPED_ITEM) {
Dmsg1(100, "File %s is a FILE_ATTRIBUTES_DEDUPED_ITEM\n", ofname);
}
/*
* Restore the sparse file attribute on the restored file.
*/
Expand Down

0 comments on commit 7804e55

Please sign in to comment.