-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSymlinkBackup.cpp
More file actions
111 lines (90 loc) · 6.85 KB
/
Copy pathSymlinkBackup.cpp
File metadata and controls
111 lines (90 loc) · 6.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// SymlinkBackup.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include "SymlinkBackupRestoreCommon.h"
int main(int argc, char* argv[])
{
bool interactiveMode = true;
for (int i = 0; i < argc; ++i)
{
if (strstr(argv[i], "task"))
interactiveMode = false;
}
wchar_t startDir[MAX_PATH];
const DWORD startDirLen = GetCurrentDirectoryW((DWORD)ARRAY_SIZE(startDir), startDir);
startDir[startDirLen] = '*';
startDir[startDirLen + 1] = 0;
WIN32_FIND_DATA findData = {};
HANDLE hFind = FindFirstFileW(startDir, &findData);
startDir[startDirLen] = 0;
if (hFind == INVALID_HANDLE_VALUE)
{
printf("Unable to find files in folder %ls\n", startDir);
system("pause");
return -1;
}
std::vector<Symlink_s> fileSymlinks;
std::vector<Symlink_s> dirSymlinks;
std::vector<std::wstring> dirsToVisit;
std::wstring currDir = startDir;
for (;;)
{
if (findData.dwFileAttributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))
goto next_file;
if (!wcscmp(findData.cFileName, L".") || !wcscmp(findData.cFileName, L".."))
goto next_file;
if (findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
{
printf("Found symbolic link: %ls\n", findData.cFileName);
const std::wstring symlinkSourceFilename = currDir + findData.cFileName;
const HANDLE hSymlinkTarget = OpenExistingFile(symlinkSourceFilename.c_str());
wchar_t symlinkTargetFilename[MAX_PATH] = {};
DWORD symlinkTargetFilenameLen = GetFinalPathNameByHandleW(hSymlinkTarget, symlinkTargetFilename, (DWORD)ARRAY_SIZE(symlinkTargetFilename) - 1, FILE_NAME_NORMALIZED);
CloseHandle(hSymlinkTarget);
printf("\tSymbolic link target: %ls\n\n", symlinkTargetFilename);
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
dirSymlinks.push_back({ std::move(symlinkSourceFilename), symlinkTargetFilename });
else
fileSymlinks.push_back({ std::move(symlinkSourceFilename), symlinkTargetFilename });
}
else if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//printf("Found directory: %ls%ls\n", currDir.c_str(), findData.cFileName);
dirsToVisit.push_back(currDir + std::wstring(findData.cFileName) + L"\\");
}
next_file:
if (!FindNextFile(hFind, &findData))
{
if (dirsToVisit.empty())
break;
FindClose(hFind);
do
{
currDir = std::move(dirsToVisit.back());
dirsToVisit.pop_back();
hFind = FindFirstFileW((currDir + L"*").c_str(), &findData);
} while (hFind == INVALID_HANDLE_VALUE && !dirsToVisit.empty());
if (hFind == INVALID_HANDLE_VALUE)
break;
}
}
FindClose(hFind);
std::wstring output;
output.reserve(4096);
if (!fileSymlinks.empty() || !dirSymlinks.empty())
{
const HANDLE hSymlinkBackupFile = CreateFileW(SYMLINK_BACKUP_FILENAME, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr );
DWORD bytesWritten = -1;
if (fileSymlinks.empty())
output += L"\n";
for (const Symlink_s& symlink : fileSymlinks)
output += symlink.source + L"," + symlink.target + L"\n";
output += L"\n";
for (const Symlink_s& symlink : dirSymlinks)
output += symlink.source + L"," + symlink.target + L"\n";
WriteFile(hSymlinkBackupFile, output.c_str(), (DWORD)((output.length()) * sizeof(wchar_t)), &bytesWritten, nullptr);
CloseHandle(hSymlinkBackupFile);
}
if (interactiveMode)
system("pause");
return 0;
}