diff options
author | Vladislav Vaintroub <wlad@mariadb.com> | 2021-12-21 12:24:35 +0100 |
---|---|---|
committer | Vladislav Vaintroub <wlad@mariadb.com> | 2022-01-05 10:46:54 +0100 |
commit | 2a6e08690223fd15bd5cb261efe9b997fa2d6026 (patch) | |
tree | f98aa721dd8762ba61c806aeafa3db84a53db290 | |
parent | 3712808ad2933a7a866e36114fa3c63a8630137d (diff) | |
download | mariadb-git-2a6e08690223fd15bd5cb261efe9b997fa2d6026.tar.gz |
MDEV-27335 Windows, MSI - Bring the datadir location into the instance config UI
-rw-r--r-- | win/packaging/ca/CustomAction.cpp | 122 | ||||
-rw-r--r-- | win/packaging/ca/CustomAction.def | 2 | ||||
-rw-r--r-- | win/packaging/extra.wxs.in | 29 |
3 files changed, 93 insertions, 60 deletions
diff --git a/win/packaging/ca/CustomAction.cpp b/win/packaging/ca/CustomAction.cpp index ccb83c7b0c6..cbef4d2ee41 100644 --- a/win/packaging/ca/CustomAction.cpp +++ b/win/packaging/ca/CustomAction.cpp @@ -161,70 +161,100 @@ static void EscapeCommandLine(const wchar_t *in, wchar_t *out, size_t buflen) } out[pos++]= 0; } + +bool IsDirectoryEmptyOrNonExisting(const wchar_t *dir) { + wchar_t wildcard[MAX_PATH+3]; + WIN32_FIND_DATAW data; + HANDLE h; + wcscpy_s(wildcard, MAX_PATH, dir); + wcscat_s(wildcard, MAX_PATH, L"*.*"); + bool empty= true; + h= FindFirstFile(wildcard, &data); + if (h != INVALID_HANDLE_VALUE) + { + for (;;) + { + if (wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) + { + empty= false; + break; + } + if (!FindNextFile(h, &data)) + break; + } + FindClose(h); + } + return empty; +} + /* - Check for if directory is empty during install, - sets "<PROPERTY>_NOT_EMPTY" otherise + Check for valid data directory is empty during install + A valid data directory is non-existing, or empty. + + In addition, it must be different from any directories that + are going to be installed. This is required. because the full + directory is removed on a feature uninstall, and we do not want + it to be lib or bin. */ -extern "C" UINT __stdcall CheckDirectoryEmpty(MSIHANDLE hInstall, - const wchar_t *PropertyName) +extern "C" UINT __stdcall CheckDataDirectory(MSIHANDLE hInstall) { - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - wchar_t buf[MAX_PATH]; - DWORD len = MAX_PATH; - WIN32_FIND_DATAW data; - HANDLE h; + HRESULT hr= S_OK; + UINT er= ERROR_SUCCESS; + wchar_t datadir[MAX_PATH]; + DWORD len= MAX_PATH; bool empty; + wchar_t *path= 0; - hr = WcaInitialize(hInstall, __FUNCTION__); + MsiGetPropertyW(hInstall, L"DATADIR", datadir, &len); + hr= WcaInitialize(hInstall, __FUNCTION__); ExitOnFailure(hr, "Failed to initialize"); WcaLog(LOGMSG_STANDARD, "Initialized."); - MsiGetPropertyW(hInstall, PropertyName, buf, &len); - wcscat_s(buf, MAX_PATH, L"*.*"); + WcaLog(LOGMSG_STANDARD, "Checking files in %S", datadir); + empty= IsDirectoryEmptyOrNonExisting(datadir); + if (empty) + WcaLog(LOGMSG_STANDARD, "DATADIR is empty or non-existent"); + else + WcaLog(LOGMSG_STANDARD, "DATADIR is NOT empty"); + + if (!empty) + { + WcaSetProperty(L"DATADIRERROR", L"data directory exist and not empty"); + goto LExit; + } + WcaSetProperty(L"DATADIRERROR", L""); - WcaLog(LOGMSG_STANDARD, "Checking files in %S", buf); - h= FindFirstFile(buf, &data); - if (h != INVALID_HANDLE_VALUE) + WcaGetFormattedString(L"[INSTALLDIR]",&path); + if (path && !wcsicmp(datadir, path)) { - empty= true; - for(;;) - { - if (wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) - { - empty= false; - break; - } - if (!FindNextFile(h, &data)) - break; - } - FindClose(h); + WcaSetProperty(L"DATADIRERROR", L"data directory can not be " + L"installation root directory"); + ReleaseStr(path); + goto LExit; } - else + for (auto dir : + {L"[INSTALLDIR]bin\\", L"[INSTALLDIR]include\\", + L"[INSTALLDIR]lib\\", L"[INSTALLDIR]share\\"}) { - /* Non-existent directory, we handle it as empty */ - empty = true; + WcaGetFormattedString(dir, &path); + if (path && !wcsnicmp(datadir, path, wcslen(path))) + { + const wchar_t *subdir= dir + sizeof("[INSTALLDIR]") - 1; + wchar_t msg[MAX_PATH]= L"data directory conflicts with '"; + wcsncat_s(msg, subdir, wcslen(subdir) - 1); + wcscat_s(msg, L"' directory, which is part of this installation"); + WcaSetProperty(L"DATADIRERROR", msg); + ReleaseStr(path); + goto LExit; + } + ReleaseStr(path); + path= 0; } - - if(empty) - WcaLog(LOGMSG_STANDARD, "Directory %S is empty or non-existent", - PropertyName); - else - WcaLog(LOGMSG_STANDARD, "Directory %S is NOT empty", PropertyName); - - wcscpy_s(buf, MAX_PATH, PropertyName); - wcscat_s(buf, L"NOTEMPTY"); - WcaSetProperty(buf, empty? L"":L"1"); - LExit: return WcaFinalize(er); } -extern "C" UINT __stdcall CheckDataDirectoryEmpty(MSIHANDLE hInstall) -{ - return CheckDirectoryEmpty(hInstall, L"DATADIR"); -} bool CheckServiceExists(const wchar_t *name) { diff --git a/win/packaging/ca/CustomAction.def b/win/packaging/ca/CustomAction.def index 0be77a97a08..aed69cf7827 100644 --- a/win/packaging/ca/CustomAction.def +++ b/win/packaging/ca/CustomAction.def @@ -5,6 +5,6 @@ PresetDatabaseProperties RemoveDataDirectory CreateDatabaseRollback CheckDatabaseProperties -CheckDataDirectoryEmpty +CheckDataDirectory CheckDBInUse CheckServiceUpgrades diff --git a/win/packaging/extra.wxs.in b/win/packaging/extra.wxs.in index e886ed87d06..d003cea26d6 100644 --- a/win/packaging/extra.wxs.in +++ b/win/packaging/extra.wxs.in @@ -230,12 +230,22 @@ <Control Id="CheckBoxUTF8" Type="CheckBox" X="8" Y="154" Width="250" Height="18" Property="UTF8" CheckBoxValue="1" TabSkip="no"> <Text>{\Font1}Use UTF8 as default server's character set</Text> </Control> - + <Control Type="Text" Id="Text11" Width="67" Height="17" X="8" Y="190" Text="{\Font1}Data directory" /> + <Control Type="PathEdit" Id="TxtDir" Width="175" Height="18" X="80" Y="190" Property="DATADIR"> + </Control> + <Control Id="btnDirBrowse" Type="PushButton" Width="56" Height="17" X="278" Y="190" Text="Browse..."> + <Publish Property="_BrowseProperty" Value="DATADIR" Order="1">1</Publish> + <Publish Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish> + </Control> <!-- Navigation buttons--> <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="&Back"> <Publish Event="NewDialog" Value="CustomizeDlg">1</Publish> </Control> <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="&Next"> + <Publish Event="DoAction" Value="CheckDataDirectory">1</Publish> + <Publish Property="WarningText" Value="Invalid data directory, choose a different one. Error: [DATADIRERROR]"> + DATADIRERROR + </Publish> <Publish Property="WarningText" Value="Passwords do not match."><![CDATA[PASSWORD <> RootPasswordConfirm]]></Publish> <Publish Event="SpawnDialog" Value="WarningDlg"><![CDATA[WarningText <>""]]></Publish> <Publish Property="SERVICENAME" Value="MariaDB">NOT SERVICENAME AND NOT WarningText</Publish> @@ -335,7 +345,7 @@ </UI> <Property Id="CRLF" Value="
" /> - <CustomAction Id="CheckDataDirectoryEmpty" BinaryKey="wixca.dll" DllEntry="CheckDataDirectoryEmpty" Execute="immediate" Impersonate="yes"/> + <CustomAction Id="CheckDataDirectory" BinaryKey="wixca.dll" DllEntry="CheckDataDirectory" Execute="immediate" Impersonate="yes"/> <!-- What to do when navigation buttons are clicked --> <UI Id="MyWixUI_Mondo"> <UIRef Id="WixUI_FeatureTree" /> @@ -355,13 +365,6 @@ <Publish Dialog="CustomizeDlg" Control="Back" Event="NewDialog" Value="NewOrUpgradeInstanceDlg" Order="999"> NOT Installed AND UpgradableServiceFound </Publish> - <Publish Dialog="CustomizeDlg" Control="Next" Event="DoAction" Value="CheckDataDirectoryEmpty" Order="1"><![CDATA[&DBInstance=3 AND NOT !DBInstance=3]]></Publish> - <Publish Dialog="CustomizeDlg" Property="DATADIRNOTEMPTY" Control="Next" Order="1"><![CDATA[NOT(&DBInstance=3 AND NOT !DBInstance=3)]]></Publish> - <Publish Dialog="CustomizeDlg" Control="Next" Property="WarningText" Order="2" - Value="Selected data directory [DATADIR] is not empty. Either clean it, or choose another location for 'Database Instance' feature."> - DATADIRNOTEMPTY - </Publish> - <Publish Dialog="CustomizeDlg" Control="Next" Event="SpawnDialog" Value="WarningDlg" Order="3">WarningText</Publish> <Publish Dialog="CustomizeDlg" Control="Next" Event="NewDialog" Value="ConfirmDataCleanupDlg" Order="4"> <![CDATA[(&DBInstance=2) AND (!DBInstance=3)]]> </Publish> @@ -634,13 +637,13 @@ Property="FailureProgram" Execute="deferred" /> - <CustomAction Id='ErrorDataDirNotEmpty' - Error='Chosen data directory [DATADIR] is not empty. It must be empty prior to installation.'/> + <CustomAction Id='ErrorDataDir' + Error='Invalid data directory, choose a different one. Error : [DATADIRERROR]'/> <InstallExecuteSequence> - <Custom Action="CheckDataDirectoryEmpty" After="CostFinalize"> + <Custom Action="CheckDataDirectory" After="CostFinalize"> <![CDATA[&DBInstance=3 AND NOT !DBInstance=3 AND OLDERVERSIONBEINGUPGRADED=""]]> </Custom> - <Custom Action="ErrorDataDirNotEmpty" After="CheckDataDirectoryEmpty" >DATADIRNOTEMPTY</Custom> + <Custom Action="ErrorDataDir" After="CheckDataDirectory">DATADIRERROR</Custom> <Custom Action="CheckDatabaseProperties" Before="CreateDatabaseCommand">SERVICENAME</Custom> <Custom Action="CreateDatabaseCommand" After="CostFinalize" > <![CDATA[&DBInstance=3 AND NOT !DBInstance=3 AND OLDERVERSIONBEINGUPGRADED=""]]> |