Skip to content

Commit

Permalink
Allow ysetup to install from local packages (for CDs etc)
Browse files Browse the repository at this point in the history
  • Loading branch information
malxau committed Jul 25, 2019
1 parent 99190e5 commit 3eeeaee
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 8 deletions.
41 changes: 36 additions & 5 deletions pkglib/remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,10 @@ YoriPkgCollectPackagesFromSource(
including any sources they refer to, and build a complete list of packages
found from all sources.
@param CustomSource Optionally specifies a source for packages. If not
specified, the INI from NewDirectory is used, and if that's not
present, fallback to default sources.
@param NewDirectory Optionally specifies an install directory. If not
specified, the directory of the currently running application is
used.
Expand All @@ -627,6 +631,7 @@ YoriPkgCollectPackagesFromSource(
*/
BOOL
YoriPkgCollectAllSourcesAndPackages(
__in_opt PYORI_STRING CustomSource,
__in_opt PYORI_STRING NewDirectory,
__out PYORI_LIST_ENTRY SourcesList,
__out PYORI_LIST_ENTRY PackageList
Expand All @@ -644,9 +649,18 @@ YoriPkgCollectAllSourcesAndPackages(
YoriLibInitializeListHead(PackageList);
YoriLibInitializeListHead(SourcesList);

if (!YoriPkgCollectSourcesFromIniWithDefaults(&PackagesIni, SourcesList, NULL)) {
YoriLibFreeStringContents(&PackagesIni);
return FALSE;
if (CustomSource != NULL) {
Source = YoriPkgAllocateRemoteSource(CustomSource);
if (Source == NULL) {
YoriLibFreeStringContents(&PackagesIni);
return FALSE;
}
YoriLibAppendList(SourcesList, &Source->SourceList);
} else {
if (!YoriPkgCollectSourcesFromIniWithDefaults(&PackagesIni, SourcesList, NULL)) {
YoriLibFreeStringContents(&PackagesIni);
return FALSE;
}
}

//
Expand Down Expand Up @@ -729,7 +743,7 @@ YoriPkgDisplayAvailableRemotePackages()
PYORI_LIST_ENTRY PackageEntry;
PYORIPKG_REMOTE_PACKAGE Package;

YoriPkgCollectAllSourcesAndPackages(NULL, &SourcesList, &PackageList);
YoriPkgCollectAllSourcesAndPackages(NULL, NULL, &SourcesList, &PackageList);

//
// Display the packages we found.
Expand Down Expand Up @@ -795,6 +809,10 @@ YoriPkgFindRemotePackageMatchingArchitecture(
@param PackageNameCount The number of elements in the PackageName array.
@param CustomSource Optionally specifies a source for packages. If not
specified, the INI from NewDirectory is used, and if that's not
present, fallback to default sources.
@param NewDirectory Optionally specifies an install directory. If not
specified, the directory of the currently running application is
used.
Expand All @@ -816,6 +834,7 @@ DWORD
YoriPkgFindRemotePackages(
__in PYORI_STRING PackageNames,
__in DWORD PackageNameCount,
__in_opt PYORI_STRING CustomSource,
__in_opt PYORI_STRING NewDirectory,
__in_opt PYORI_STRING MatchVersion,
__in_opt PYORI_STRING MatchArch,
Expand All @@ -833,7 +852,7 @@ YoriPkgFindRemotePackages(
DWORD InstallCount = 0;
BOOL PkgInstalled;

YoriPkgCollectAllSourcesAndPackages(NewDirectory, &SourcesList, &PackageList);
YoriPkgCollectAllSourcesAndPackages(CustomSource, NewDirectory, &SourcesList, &PackageList);

for (PkgIndex = 0; PkgIndex < PackageNameCount; PkgIndex++) {
YoriLibInitializeListHead(&PackagesMatchingName);
Expand Down Expand Up @@ -956,6 +975,10 @@ YoriPkgFindRemotePackages(
@param PackageNameCount The number of elements in the PackageName array.
@param CustomSource Optionally specifies a source for packages. If not
specified, the INI from NewDirectory is used, and if that's not
present, fallback to default sources.
@param NewDirectory Optionally specifies an install directory. If not
specified, the directory of the currently running application is
used.
Expand All @@ -973,6 +996,7 @@ BOOL
YoriPkgInstallRemotePackages(
__in PYORI_STRING PackageNames,
__in DWORD PackageNameCount,
__in_opt PYORI_STRING CustomSource,
__in_opt PYORI_STRING NewDirectory,
__in_opt PYORI_STRING MatchVersion,
__in_opt PYORI_STRING MatchArch
Expand Down Expand Up @@ -1013,6 +1037,7 @@ YoriPkgInstallRemotePackages(

MatchingPackageCount = YoriPkgFindRemotePackages(PackageNames,
PackageNameCount,
CustomSource,
NewDirectory,
MatchVersion,
MatchArch,
Expand Down Expand Up @@ -1070,6 +1095,10 @@ YoriPkgInstallRemotePackages(
@param PackageNameCount The number of elements in the PackageName array.
@param CustomSource Optionally specifies a source for packages. If not
specified, the INI from NewDirectory is used, and if that's not
present, fallback to default sources.
@param NewDirectory Optionally specifies an install directory. If not
specified, the directory of the currently running application is
used.
Expand All @@ -1084,6 +1113,7 @@ DWORD
YoriPkgGetRemotePackageUrls(
__in PYORI_STRING PackageNames,
__in DWORD PackageNameCount,
__in_opt PYORI_STRING CustomSource,
__in_opt PYORI_STRING NewDirectory,
__out PYORI_STRING * PackageUrls
)
Expand All @@ -1101,6 +1131,7 @@ YoriPkgGetRemotePackageUrls(

MatchingPackageCount = YoriPkgFindRemotePackages(PackageNames,
PackageNameCount,
CustomSource,
NewDirectory,
NULL,
NULL,
Expand Down
2 changes: 2 additions & 0 deletions pkglib/yoripkg.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ BOOL
YoriPkgInstallRemotePackages(
__in PYORI_STRING PackageNames,
__in DWORD PackageNameCount,
__in_opt PYORI_STRING CustomSource,
__in_opt PYORI_STRING NewDirectory,
__in_opt PYORI_STRING MatchVersion,
__in_opt PYORI_STRING MatchArch
Expand All @@ -135,6 +136,7 @@ DWORD
YoriPkgGetRemotePackageUrls(
__in PYORI_STRING PackageNames,
__in DWORD PackageNameCount,
__in_opt PYORI_STRING CustomSource,
__in_opt PYORI_STRING NewDirectory,
__out PYORI_STRING * PackageUrls
);
Expand Down
2 changes: 1 addition & 1 deletion ypm/ypm.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ ENTRYPOINT(
YoriLibOutput(YORI_LIB_OUTPUT_STDERR, _T("ypm: missing package name\n"));
return EXIT_FAILURE;
}
YoriPkgInstallRemotePackages(&ArgV[StartArg], PkgCount, NULL, NewVersion, NewArch);
YoriPkgInstallRemotePackages(&ArgV[StartArg], PkgCount, NULL, NULL, NewVersion, NewArch);
} else if (Op == YpmOpInstallSource) {
if (StartArg == 0 || StartArg >= ArgC) {
YoriPkgInstallSourceForInstalledPackages();
Expand Down
118 changes: 116 additions & 2 deletions ysetup/ysetup.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,98 @@ YsetupHelp()
return TRUE;
}

/**
A list of subdirectories from the application to check for packages.
*/
CONST LPTSTR SetupLocalPathsToCheck[] = {
_T("pkg"),
_T("yori"),
_T("ypm"),
_T("ysetup")
};

/**
See if there are local packages for installation without using the internet.
This probes subdirectories of the application's directory. Subdirectories
are used to avoid squatting in the downloads folder, ie., not allowing a
website drive-by to populate the downloads folder with a file that would
manipulate the installer.
@param LocalPath On successful completion, populated with a referenced string
describing the local package location to use.
@return TRUE to indicate that a local package location has been found which
should be used, and FALSE to indicate default package locations
should be used instead.
*/
BOOL
SetupFindLocalPkgPath(
__out PYORI_STRING LocalPath
)
{
DWORD Index;
int Result;
YORI_STRING RelativePathToProbe;
YORI_STRING FullPathToProbe;

YoriLibInitEmptyString(&RelativePathToProbe);
YoriLibInitEmptyString(&FullPathToProbe);
for (Index = 0; Index < sizeof(SetupLocalPathsToCheck)/sizeof(SetupLocalPathsToCheck[0]); Index++) {

//
// Create a path using the specification for the directory of the
// running process
//

Result = YoriLibYPrintf(&RelativePathToProbe, _T("~APPDIR\\%s\\pkglist.ini"), SetupLocalPathsToCheck[Index]);
if (Result == -1) {
YoriLibFreeStringContents(&RelativePathToProbe);
YoriLibFreeStringContents(&FullPathToProbe);
return FALSE;
}

//
// Turn that into a full path for the benefit of Win32
//

if (!YoriLibUserStringToSingleFilePath(&RelativePathToProbe, TRUE, &FullPathToProbe)) {
YoriLibFreeStringContents(&RelativePathToProbe);
YoriLibFreeStringContents(&FullPathToProbe);
return FALSE;
}

//
// See if it exists
//

if (GetFileAttributes(FullPathToProbe.StartOfString) != (DWORD)-1) {
YoriLibFreeStringContents(&RelativePathToProbe);

//
// Remove pkglist.ini. Note that sizeof includes the NULL so
// this removes the trailing slash too
//

FullPathToProbe.LengthInChars -= sizeof("pkglist.ini");
FullPathToProbe.StartOfString[FullPathToProbe.LengthInChars] = '\0';
YoriLibOutput(YORI_LIB_OUTPUT_STDOUT, _T("Found local packages at %y\n"), &FullPathToProbe);
memcpy(LocalPath, &FullPathToProbe, sizeof(YORI_STRING));
return TRUE;
}

YoriLibFreeStringContents(&FullPathToProbe);

}

//
// No local path found, try the internet
//

YoriLibFreeStringContents(&RelativePathToProbe);
YoriLibFreeStringContents(&FullPathToProbe);
return FALSE;
}

/**
Install the default set of packages to a specified directory.
Expand All @@ -71,13 +163,23 @@ SetupInstallToDirectory(
__inout PYORI_STRING InstallDirectory
)
{
YORI_STRING LocalPath;
PYORI_STRING CustomSource;
YORI_STRING PkgNames[4];

YoriLibInitEmptyString(&LocalPath);
CustomSource = NULL;

if (SetupFindLocalPkgPath(&LocalPath)) {
CustomSource = &LocalPath;
}

if (!YoriLibCreateDirectoryAndParents(InstallDirectory)) {
DWORD Err = GetLastError();
LPTSTR ErrText = YoriLibGetWinErrorText(Err);
YoriLibOutput(YORI_LIB_OUTPUT_STDERR, _T("ysetup: Could not create installation directory %y: %s\n"), InstallDirectory, ErrText);
YoriLibFreeWinErrorText(ErrText);
YoriLibFreeStringContents(&LocalPath);
return FALSE;
}

Expand All @@ -86,9 +188,12 @@ SetupInstallToDirectory(
YoriLibConstantString(&PkgNames[2], _T("yori-typical"));
YoriLibConstantString(&PkgNames[3], _T("yori-completion"));

if (YoriPkgInstallRemotePackages(PkgNames, sizeof(PkgNames)/sizeof(PkgNames[0]), InstallDirectory, NULL, NULL)) {
if (YoriPkgInstallRemotePackages(PkgNames, sizeof(PkgNames)/sizeof(PkgNames[0]), CustomSource, InstallDirectory, NULL, NULL)) {
YoriLibFreeStringContents(&LocalPath);
return TRUE;
}

YoriLibFreeStringContents(&LocalPath);
return FALSE;
}

Expand Down Expand Up @@ -180,6 +285,8 @@ SetupInstallSelectedFromDialog(
YORI_STRING StatusText;
PYORI_STRING PkgNames;
PYORI_STRING PackageUrls;
YORI_STRING LocalPath;
PYORI_STRING CustomSource;
DWORD PkgCount;
DWORD PkgIndex;
DWORD PkgUrlCount;
Expand All @@ -190,6 +297,9 @@ SetupInstallSelectedFromDialog(
InstallTypeComplete = 3
} InstallType;

YoriLibInitEmptyString(&LocalPath);
CustomSource = NULL;

//
// Query the install directory and attempt to create it
//
Expand Down Expand Up @@ -307,9 +417,12 @@ SetupInstallSelectedFromDialog(
// Obtain URLs for the specified packages.
//

if (SetupFindLocalPkgPath(&LocalPath)) {
CustomSource = &LocalPath;
}
YoriLibInitEmptyString(&StatusText);
SetDlgItemText(hDlg, IDC_STATUS, _T("Obtaining package URLs..."));
PkgUrlCount = YoriPkgGetRemotePackageUrls(PkgNames, PkgIndex, &InstallDir, &PackageUrls);
PkgUrlCount = YoriPkgGetRemotePackageUrls(PkgNames, PkgIndex, CustomSource, &InstallDir, &PackageUrls);

if (PkgUrlCount != PkgCount) {
MessageBox(hDlg, _T("Could not locate selected package files."), _T("Installation failed."), MB_ICONSTOP);
Expand Down Expand Up @@ -422,6 +535,7 @@ SetupInstallSelectedFromDialog(
YoriLibDereference(PackageUrls);
YoriLibFreeStringContents(&InstallDir);
YoriLibFreeStringContents(&StatusText);
YoriLibFreeStringContents(&LocalPath);
YoriLibFree(PkgNames);
return Result;
}
Expand Down

0 comments on commit 3eeeaee

Please sign in to comment.