58#include <config_version.h>
71#define INVALID_APPLYTO_DIR_ERROR 74
72#define REMOVE_FILE_SPEC_ERROR 71
73#define INVALID_APPLYTO_DIR_STAGED_ERROR 72
80#define PROGRESS_PREPARE_SIZE 20.0f
81#define PROGRESS_EXECUTE_SIZE 75.0f
82#define PROGRESS_FINISH_SIZE 5.0f
86#define PARENT_WAIT 5000
91void CleanupElevatedMacUpdate(
bool aFailureOccurred);
92bool IsOwnedByGroupAdmin(
const char* aAppBundle);
93bool IsRecursivelyWritable(
const char* aPath);
96bool ObtainUpdaterArguments(
int* argc,
char*** argv);
97bool ServeElevatedUpdate(
int argc,
const char** argv);
98void SetGroupOwnershipAndPermissions(
const char* aAppBundle);
99struct UpdateServerThreadArgs
107# define SSIZE_MAX LONG_MAX
112#if defined(UNIX) && !defined(MACOSX)
116#if defined(VERIFY_MAR_SIGNATURE) && !defined(_WIN32) && !defined(MACOSX)
122#ifdef MAINTENANCE_SERVICE
123#include "registrycertificates.h"
127 LPCWSTR siblingFilePath,
128 LPCWSTR newFileName);
134#define EXIT_WHEN_ELEVATED(path, handle, retCode) \
136 if (handle != INVALID_HANDLE_VALUE) { \
137 CloseHandle(handle); \
139 if (_waccess(path, F_OK) == 0 && NS_tremove(path) != 0) { \
152#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
159crc32(
const unsigned char *buf,
unsigned int len)
161 unsigned int crc = 0xffffffffL;
163 const unsigned char *
end = buf + len;
164 for (; buf !=
end; ++buf)
185 if (
mFile !=
nullptr)
257 for (
d = delims; *
d !=
NS_T(
'\0'); ++
d)
277 for (
d = delims; *
d !=
NS_T(
'\0'); ++
d)
294#if defined(_WIN32) && defined(MAINTENANCE_SERVICE)
296EnvHasValue(
const char *name)
298 const char *val = getenv(name);
299 return (val && *val);
334bool is_userprofile_in_instdir()
375 if (abs_path[1] !=
':' && abs_path[2] !=
'\\')
378 if (abs_path[0] !=
'/')
389 if (0 != strncmp(abs_path,
prefix, len))
391 return abs_path + len + 1;
410 LOG((
"get_valid_path: unable to determine path: " LOG_S,
line));
415 if (path[0] ==
NS_T(
'/'))
417 LOG((
"get_valid_path: path must be relative: " LOG_S, path));
423 if (path[0] ==
NS_T(
'\\') || path[1] ==
NS_T(
':'))
425 LOG((
"get_valid_path: path must be relative: " LOG_S, path));
435 LOG((
"get_valid_path: directory paths must have a trailing forward " \
436 "slash: " LOG_S, path));
448 LOG((
"get_valid_path: paths must not contain '..': " LOG_S, path));
460 size_t len = lenQuote + lenPath + lenQuote + 1;
481 (void) _wchmod(path, _S_IREAD | _S_IWRITE);
484 if (!stat(path, &
fs) && !(
fs.st_mode & S_IWUSR))
486 (void)chmod(path,
fs.st_mode | S_IWUSR);
496 LOG((
"ensure_remove: failed to remove file: " LOG_S ", rv: %d, err: %d",
503 bool continueEnumOnFailure =
false)
514 if (!S_ISDIR(sInfo.st_mode))
525 LOG((
"ensure_remove_recursive: unable to open directory: " LOG_S
526 ", rv: %d, err: %d", path, rv, errno));
536 NS_tsnprintf(childPath,
sizeof(childPath)/
sizeof(childPath[0]),
537 NS_T(
"%s/%s"), path, entry->d_name);
539 if (rv && !continueEnumOnFailure)
554 LOG((
"ensure_remove_recursive: unable to remove directory: " LOG_S
555 ", rv: %d, err: %d", path, rv, errno));
568 if (flags[0] !=
NS_T(
'r'))
601 if (
NS_tstat(path, &ss) != 0 || ss.st_mode != options)
623 if (rv ==
OK && *path)
627 if (rv < 0 && errno != EEXIST)
629 LOG((
"ensure_parent_dir: failed to create directory: " LOG_S ", " \
630 "err: %d", path, errno));
651 LOG((
"ensure_copy_symlink: failed to read the link: " LOG_S ", err: %d",
655 rv = symlink(target, dest);
658 LOG((
"ensure_copy_symlink: failed to create the new link: " LOG_S ", target: " LOG_S " err: %d",
659 dest, target, errno));
671 bool result = CopyFileW(path, dest,
false);
674 LOG((
"ensure_copy: failed to copy the file " LOG_S " over to " LOG_S ", lasterr: %x",
675 path, dest, GetLastError()));
684 LOG((
"ensure_copy: failed to read file status info: " LOG_S ", err: %d",
690 if (S_ISLNK(ss.st_mode))
699 LOG((
"ensure_copy: failed to open the file for reading: " LOG_S ", err: %d",
706 LOG((
"ensure_copy: failed to open the file for writing: " LOG_S ", err: %d",
714 const int blockSize = 32 * 1024;
715 void* buffer = malloc(blockSize);
719 while (!feof(
infile.get()))
721 size_t read = fread(buffer, 1, blockSize,
infile);
724 LOG((
"ensure_copy: failed to read the file: " LOG_S ", err: %d",
732 while (written < read)
734 size_t nCount = read - written;
736 if (chunkWritten !=
nCount)
738 LOG((
"ensure_copy: failed to write the file: " LOG_S ", err: %d",
744 written += chunkWritten;
772 for (
int i = 0; i < static_cast<int>(
N); ++
i)
793 LOG((
"ensure_copy_recursive: path doesn't exist: " LOG_S ", rv: %d, err: %d",
799 if (S_ISLNK(sInfo.st_mode))
805 if (!S_ISDIR(sInfo.st_mode))
811 if (rv < 0 && errno != EEXIST)
813 LOG((
"ensure_copy_recursive: could not create destination directory: " LOG_S ", rv: %d, err: %d",
824 LOG((
"ensure_copy_recursive: path is not a directory: " LOG_S ", rv: %d, err: %d",
835 NS_tsnprintf(childPath,
sizeof(childPath)/
sizeof(childPath[0]),
836 NS_T(
"%s/%s"), path, entry->d_name);
837 if (skiplist.
find(childPath))
842 NS_tsnprintf(childPathDest,
sizeof(childPathDest)/
sizeof(childPathDest[0]),
843 NS_T(
"%s/%s"), dest, entry->d_name);
858 bool allowDirs =
false)
868 LOG((
"rename_file: failed to read file status info: " LOG_S ", " \
869 "err: %d", spath, errno));
873 if (!S_ISREG(spathInfo.st_mode))
875 if (allowDirs && !S_ISDIR(spathInfo.st_mode))
877 LOG((
"rename_file: path present, but not a file: " LOG_S ", err: %d",
883 LOG((
"rename_file: proceeding to rename the directory"));
891 LOG((
"rename_file: destination file exists and could not be " \
892 "removed: " LOG_S, dpath));
899 LOG((
"rename_file: failed to rename file - src: " LOG_S ", " \
900 "dst:" LOG_S ", err: %d", spath, dpath, errno));
911static int remove_recursive_on_reboot(
const NS_tchar *path,
const NS_tchar *deleteDir)
921 if (!S_ISDIR(sInfo.st_mode))
924 GetTempFileNameW(deleteDir, L
"rep", 0, tmpDeleteFile);
927 if (MoveFileEx(rv ? path : tmpDeleteFile,
nullptr, MOVEFILE_DELAY_UNTIL_REBOOT))
929 LOG((
"remove_recursive_on_reboot: file will be removed on OS reboot: "
930 LOG_S, rv ? path : tmpDeleteFile));
934 LOG((
"remove_recursive_on_reboot: failed to schedule OS reboot removal of "
935 "file: " LOG_S, rv ? path : tmpDeleteFile));
946 LOG((
"remove_recursive_on_reboot: unable to open directory: " LOG_S
958 NS_tsnprintf(childPath,
sizeof(childPath)/
sizeof(childPath[0]),
959 NS_T(
"%s/%s"), path, entry->d_name);
964 remove_recursive_on_reboot(childPath, deleteDir);
976 LOG((
"remove_recursive_on_reboot: unable to remove directory: " LOG_S
977 ", rv: %d, err: %d", path, rv, errno));
1005 NS_tsnprintf(relBackup,
sizeof(relBackup) /
sizeof(relBackup[0]),
1010 LOG((
"backup_restore: backup file doesn't exist: " LOG_S, relBackup));
1025 NS_tsnprintf(relBackup,
sizeof(relBackup) /
sizeof(relBackup[0]),
1038 LOG((
"backup_discard: unable to remove: " LOG_S, relBackup));
1040 GetTempFileNameW(gDeleteDirPath, L
"moz", 0, path);
1043 LOG((
"backup_discard: failed to rename file:" LOG_S ", dst:" LOG_S,
1044 relBackup, relPath));
1052 if (MoveFileEx(path,
nullptr, MOVEFILE_DELAY_UNTIL_REBOOT))
1054 LOG((
"backup_discard: file renamed and will be removed on OS " \
1055 "reboot: " LOG_S, relPath));
1059 LOG((
"backup_discard: failed to schedule OS reboot removal of " \
1060 "file: " LOG_S, relPath));
1124 std::unique_ptr<const NS_tchar[]>
mFile;
1169 LOG((
"failed to read file status info: " LOG_S ", err: %d",
mFile.get(),
1174 if (!S_ISREG(fileInfo.st_mode))
1183 *slash =
NS_T(
'\0');
1194 LOG((
"access failed: %d", errno));
1214 LOG((
"file cannot be removed because it does not exist; skipping"));
1223 LOG((
"backup_create failed: %d", rv));
1249 virtual void Finish(
int status);
1297 LOG((
"failed to read directory status info: " LOG_S ", err: %d",
mRelPath.get(),
1302 if (!S_ISDIR(dirInfo.st_mode))
1311 LOG((
"access failed: %d, %d", rv, errno));
1331 LOG((
"directory no longer exists; skipping"));
1351 LOG((
"directory no longer exists; skipping"));
1360 LOG((
"non-fatal error removing directory: " LOG_S "/, rv: %d, err: %d",
1374 virtual void Finish(
int status);
1436 if (!WideCharToMultiByte(CP_UTF8, 0,
mRelPath.get(), -1, sourcefile,
1439 LOG((
"error converting wchar to utf8: %d", GetLastError()));
1475 virtual void Finish(
int status);
1504 UnlockFile((HANDLE)_get_osfhandle(fileno(
mPatchStream)), (DWORD)0, (DWORD)0, (DWORD)-1, (DWORD)-1);
1520 int rv = fstat(fileno((
FILE *)ofile), &os);
1523 LOG((
"LoadSourceFile: unable to stat destination file: " LOG_S ", " \
1530 LOG((
"LoadSourceFile: destination file size %d does not match expected size %d",
1540 unsigned char *rb =
buf;
1544 size_t c = fread(rb, 1,
count, ofile);
1547 LOG((
"LoadSourceFile: error reading destination file: " LOG_S,
1562 LOG((
"LoadSourceFile: destination file crc %d does not match expected " \
1610 (void) nWrittenBytes;
1621 if (!LockFile((HANDLE)_get_osfhandle(fileno(
mPatchStream)), (DWORD)0, (DWORD)0, (DWORD)-1, (DWORD)-1))
1623 LOG((
"Couldn't lock patch file: %d", GetLastError()));
1631 LOG((
"error converting wchar to utf8: %d", GetLastError()));
1654 FILE *origfile =
nullptr;
1672 LOG((
"unable to open destination file: " LOG_S ", err: %d",
1681 LOG((
"LoadSourceFile failed"));
1691 LOG((
"failed to read file status info: " LOG_S ", err: %d",
1700#if defined(HAVE_POSIX_FALLOCATE)
1703#elif defined(_WIN32)
1704 bool shouldTruncate =
true;
1712 HANDLE hfile = CreateFileW(
mFile.get(),
1717 FILE_ATTRIBUTE_NORMAL,
1720 if (hfile != INVALID_HANDLE_VALUE)
1723 nullptr, FILE_BEGIN) != INVALID_SET_FILE_POINTER &&
1724 SetEndOfFile(hfile) != 0)
1726 shouldTruncate =
false;
1733#elif defined(MACOSX)
1738 rv = fcntl(fileno((
FILE *)ofile), F_PREALLOCATE, &
store);
1742 store.fst_flags = F_ALLOCATEALL;
1743 rv = fcntl(fileno((
FILE *)ofile), F_PREALLOCATE, &
store);
1754 if (ofile ==
nullptr)
1762 if (!shouldTruncate)
1764 fseek(ofile, 0, SEEK_SET);
1774 UnlockFile((HANDLE)_get_osfhandle(fileno(
mPatchStream)), (DWORD)0, (DWORD)0, (DWORD)-1, (DWORD)-1);
1802 virtual void Finish(
int status);
1869 virtual void Finish(
int status);
1936 virtual void Finish(
int status);
2010 const WCHAR *updateInfoDir)
2012 WCHAR workingDirectory[
MAX_PATH + 1] = { L
'\0' };
2013 wcsncpy(workingDirectory, installationDir, MAX_PATH);
2020 WCHAR inifile[
MAX_PATH + 1] = { L
'\0' };
2021 wcsncpy(inifile, installationDir, MAX_PATH);
2031 if (!GetPrivateProfileStringW(L
"PostUpdateWin", L
"ExeRelPath",
nullptr,
2032 exefile, MAX_PATH + 1, inifile))
2037 if (!GetPrivateProfileStringW(L
"PostUpdateWin", L
"ExeArg",
nullptr, exearg,
2038 MAX_PATH + 1, inifile))
2043 if (!GetPrivateProfileStringW(L
"PostUpdateWin", L
"ExeAsync", L
"TRUE",
2045 sizeof(exeasync)/
sizeof(exeasync[0]),
2052 if (wcsstr(exefile, L
"..") !=
nullptr)
2057 WCHAR exefullpath[
MAX_PATH + 1] = { L
'\0' };
2058 wcsncpy(exefullpath, installationDir, MAX_PATH);
2064#if !defined(TEST_UPDATER) && defined(MAINTENANCE_SERVICE)
2078 WCHAR slogFile[
MAX_PATH + 1] = { L
'\0' };
2079 wcsncpy(slogFile, updateInfoDir, MAX_PATH);
2085 WCHAR dummyArg[14] = { L
'\0' };
2086 wcsncpy(dummyArg, L
"argv0ignored ",
sizeof(dummyArg) /
sizeof(dummyArg[0]) - 1);
2088 size_t len = wcslen(exearg) + wcslen(dummyArg);
2089 WCHAR *cmdline = (WCHAR *) malloc((len + 1) *
sizeof(WCHAR));
2095 wcsncpy(cmdline, dummyArg, len);
2096 wcscat(cmdline, exearg);
2099 !_wcsnicmp(exeasync, L
"false", 6) ||
2100 !_wcsnicmp(exeasync, L
"0", 2))
2108 CopyFileW(slogFile, dlogFile,
false);
2110 STARTUPINFOW si = {
sizeof(si), 0};
2112 PROCESS_INFORMATION pi = {0};
2114 bool ok = CreateProcessW(exefullpath,
2129 WaitForSingleObject(pi.hProcess, INFINITE);
2131 CloseHandle(pi.hProcess);
2132 CloseHandle(pi.hThread);
2145 putenv(
const_cast<char*
>(
"NO_EM_RESTART="));
2146 putenv(
const_cast<char*
>(
"MOZ_LAUNCHED_CHILD=1"));
2153 LOG((
"Warning: chdir failed"));
2156#if defined(USE_EXECV)
2158 (void) usingService;
2159 execv(argv[0], argv);
2160#elif defined(MACOSX)
2162#elif defined(_WIN32)
2170# warning "Need implementation of LaunchCallbackApp"
2183 NS_tsnprintf(filename,
sizeof(filename)/
sizeof(filename[0]),
2195 if (file ==
nullptr)
2200 if (fwrite(aStatus, strlen(aStatus), 1, file) != 1)
2208 NS_tsnprintf(dstfilename,
sizeof(dstfilename)/
sizeof(dstfilename[0]),
2210 if (MoveFileExW(filename, dstfilename, MOVEFILE_REPLACE_EXISTING) == 0)
2233 text =
"succeeded\n";
2238 snprintf(buf,
sizeof(buf)/
sizeof(buf[0]),
"failed: %d\n", status);
2245#ifdef MAINTENANCE_SERVICE
2256IsUpdateStatusPendingService()
2259 NS_tsnprintf(filename,
sizeof(filename)/
sizeof(filename[0]),
2263 if (file ==
nullptr)
2266 char buf[32] = { 0 };
2267 fread(buf,
sizeof(buf), 1, file);
2269 const char kPendingService[] =
"pending-service";
2270 const char kAppliedService[] =
"applied-service";
2272 return (strncmp(buf, kPendingService,
2273 sizeof(kPendingService) - 1) == 0) ||
2274 (strncmp(buf, kAppliedService,
2275 sizeof(kAppliedService) - 1) == 0);
2289IsUpdateStatusSucceeded(
bool &isSucceeded)
2291 isSucceeded =
false;
2293 NS_tsnprintf(filename,
sizeof(filename)/
sizeof(filename[0]),
2297 if (file ==
nullptr)
2300 char buf[32] = { 0 };
2301 fread(buf,
sizeof(buf), 1, file);
2303 const char kSucceeded[] =
"succeeded";
2304 isSucceeded = strncmp(buf, kSucceeded,
2305 sizeof(kSucceeded) - 1) == 0;
2321#define SKIPLIST_COUNT 4
2322#elif defined(MACOSX)
2323#define SKIPLIST_COUNT 1
2325#define SKIPLIST_COUNT 3
2333 *slash =
NS_T(
'\0');
2335 LOG((
"ignore user profile directory during copy: " LOG_S, pUserProfile.get()));
2337 skiplist.
append(0, pUserProfile.get());
2367 NS_tsnprintf(destDir,
sizeof(destDir)/
sizeof(destDir[0]),
2369#elif defined(_WIN32)
2376 sizeof(destDir)/
sizeof(destDir[0])))
2386 NS_T(
"%s.bak"), destDir);
2394 LOG((
"Begin moving destDir (" LOG_S ") to tmpDir (" LOG_S ")",
2403 const int max_retries = 10;
2405 while (rv ==
WRITE_ERROR && (retries++ < max_retries))
2407 LOG((
"PerformReplaceRequest: destDir rename attempt %d failed. " \
2408 "File: " LOG_S ". Last error: %d, err: %d", retries,
2409 destDir, GetLastError(), rv));
2420 LOG((
"Moving destDir to tmpDir failed, err: %d", rv));
2425 if (is_userprofile_in_instdir())
2427 LOG((
"user profile in instdir"));
2439 LOG((
"Begin moving newDir (" LOG_S ") to destDir (" LOG_S ")",
2445 LOG((
"Moving failed. Begin copying newDir (" LOG_S ") to destDir (" LOG_S ")",
2453 LOG((
"Moving newDir to destDir failed, err: %d", rv));
2454 LOG((
"Now, try to move tmpDir back to destDir"));
2459 LOG((
"Moving tmpDir back to destDir failed, err: %d", rv2));
2466 if (is_userprofile_in_instdir())
2476 *slash =
NS_T(
'\0');
2480 NS_tstrcat(backup_user_profile, userprofile + installdir_len);
2481 LOG((
"copy user profile back from " LOG_S " to " LOG_S, backup_user_profile, userprofile));
2482 int rv2 =
rename_file(backup_user_profile, userprofile);
2485 LOG((
"failed to copy user profile back"));
2491#if !defined(_WIN32) && !defined(MACOSX)
2496 int nWrittenBytes =
NS_tsnprintf(tmpLog,
sizeof(tmpLog)/
sizeof(tmpLog[0]),
2497 NS_T(
"%s/updates/last-update.log"), tmpDir);
2498 (void) nWrittenBytes;
2502 NS_tsnprintf(destLog,
sizeof(destLog)/
sizeof(destLog[0]),
2503 NS_T(
"%s/updates/last-update.log"), destDir);
2509 LOG((
"Now, remove the tmpDir"));
2513 LOG((
"Removing tmpDir failed, err: %d", rv));
2516 NS_tsnprintf(deleteDir,
sizeof(deleteDir)/
sizeof(deleteDir[0]),
2517 NS_T(
"%s\\%s"), destDir, DELETE_DIR);
2525 remove_recursive_on_reboot(tmpDir, deleteDir);
2533 NS_tsnprintf(updatedAppDir,
sizeof(updatedAppDir)/
sizeof(updatedAppDir[0]),
2545WaitForServiceFinishThread(
void* )
2554#ifdef VERIFY_MAR_SIGNATURE
2567 const unsigned int kNumStrings = 1;
2568 const char *kUpdaterKeys =
"ACCEPTED_MAR_CHANNEL_IDS\0";
2572 updater_strings,
"Settings");
2587 fileNames.push_back(fileName);
2610 NS_tsnprintf(updatePath,
sizeof(updatePath)/
sizeof(updatePath[0]),
2613 LOG ((
"Found language update file: " LOG_S, updatePath));
2614 fileNames.push_back(updatePath);
2625#ifdef VERIFY_MAR_SIGNATURE
2627 HKEY baseKey =
nullptr;
2628 wchar_t valueName[] = L
"Image Path";
2629 wchar_t rasenh[] = L
"rsaenh.dll";
2631 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2632 L
"SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider\\Microsoft Enhanced Cryptographic Provider v1.0",
2633 0, KEY_READ | KEY_WRITE,
2634 &baseKey) == ERROR_SUCCESS)
2637 DWORD
size =
sizeof(path);
2639 if (RegQueryValueExW(baseKey, valueName, 0, &
type,
2640 (LPBYTE)path, &
size) == ERROR_SUCCESS)
2642 if (
type == REG_SZ && wcscmp(path, rasenh) == 0)
2644 wchar_t rasenhFullPath[] = L
"%SystemRoot%\\System32\\rsaenh.dll";
2645 if (RegSetValueExW(baseKey, valueName, 0, REG_SZ,
2646 (
const BYTE*)rasenhFullPath,
2647 sizeof(rasenhFullPath)) == ERROR_SUCCESS)
2661 RegSetValueExW(baseKey, valueName, 0, REG_SZ,
2662 (
const BYTE*)rasenh,
2665 RegCloseKey(baseKey);
2679 sizeof(updateSettingsPath) /
sizeof(updateSettingsPath[0]),
2681 NS_T(
"%s/Contents/Resources/update-settings.ini"),
2683 NS_T(
"%s/update-settings.ini"),
2686 (void) nWrittenBytes;
2688 if (ReadMARChannelIDs(updateSettingsPath, &MARStrings) !=
OK)
2696 LIBO_VERSION_DOTTED);
2715 std::vector<tstring> fileNames;
2718 for (
auto& fileName: fileNames)
2721 rv = archiveReader.
Open(fileName.c_str());
2724 LOG((
"Could not open " LOG_S, fileName.c_str()));
2731 LOG((
"Could not verify the signature of " LOG_S, fileName.c_str()));
2743 for (
auto& fileName: fileNames)
2746 archiveReader.
Open(fileName.c_str());
2750 int nWrittenBytes =
NS_tsnprintf(updatingDir,
sizeof(updatingDir)/
sizeof(updatingDir[0]),
2752 (void) nWrittenBytes;
2765 if (GetSystemDirectoryW(sysDir,
MAX_PATH + 1))
2789 putenv(
const_cast<char*
>(
"MOZ_TEST_PROCESS_UPDATES="));
2796 LOG((
"failed: %d", rv));
2806 LOG((
"Couldn't set access/modification time on application bundle."));
2815 LOG((
"calling QuitProgressUI"));
2821ServeElevatedUpdateThreadFunc(
void* param)
2823 UpdateServerThreadArgs* threadArgs = (UpdateServerThreadArgs*)param;
2824 gSucceeded = ServeElevatedUpdate(threadArgs->argc, threadArgs->argv);
2832void freeArguments(
int argc,
char** argv)
2834 for (
int i = 0;
i < argc;
i++)
2845 ,
const WCHAR* elevatedLockFilePath
2846 , HANDLE updateLockFileHandle
2847#elif defined(MACOSX)
2852 if (argc > callbackIndex)
2859 fprintf(stderr,
"The post update process was not launched");
2874 EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 0);
2875#elif defined(MACOSX)
2885 argc - callbackIndex,
2886 argv + callbackIndex,
2900 const int callbackIndex = 6;
2905 strstr(argv[0],
"/Library/PrivilegedHelperTools/org.mozilla.updater") != 0;
2908 if (!ObtainUpdaterArguments(&argc, &argv))
2917#if defined(VERIFY_MAR_SIGNATURE) && !defined(_WIN32) && !defined(MACOSX)
2922 if (!NSS_IsInitialized())
2924 if (NSS_NoDB_Init(
NULL) != SECSuccess)
2926 PRErrorCode error = PR_GetError();
2927 fprintf(stderr,
"Could not initialize NSS: %s (%d)",
2928 PR_ErrorToName(error), (
int) error);
2959 fprintf(stderr,
"Usage: updater patch-dir install-dir apply-to-dir [wait-pid [callback-working-dir callback-path args...]]\n");
2963 freeArguments(argc, argv);
2964 CleanupElevatedMacUpdate(
true);
2980 if (slash && !slash[1])
2982 *slash =
NS_T(
'\0');
2986 bool useService =
false;
2987 bool testOnlyFallbackKeyExists =
false;
2988 bool noServiceFallback =
false;
2992#ifdef MAINTENANCE_SERVICE
2993 useService = IsUpdateStatusPendingService();
3003 HKEY hkApp =
nullptr;
3004 RegCreateKeyExW(HKEY_CURRENT_USER, L
"Software\\Classes\\Applications",
3005 0,
nullptr, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE,
nullptr,
3008 if (RegCreateKeyExW(HKEY_CURRENT_USER,
3009 L
"Software\\Classes\\Applications\\updater.exe",
3010 0,
nullptr, REG_OPTION_VOLATILE, KEY_SET_VALUE,
nullptr,
3011 &hkApp,
nullptr) == ERROR_SUCCESS)
3013 RegSetValueExW(hkApp, L
"IsHostApp", 0, REG_NONE, 0, 0);
3014 RegSetValueExW(hkApp, L
"NoOpenWith", 0, REG_NONE, 0, 0);
3015 RegSetValueExW(hkApp, L
"NoStartPage", 0, REG_NONE, 0, 0);
3030 pid = _wtoi64(argv[4]);
3032 pid = atoi(argv[4]);
3055 if (slash && !slash[1])
3057 *slash =
NS_T(
'\0');
3061 if (!isElevated && !IsRecursivelyWritable(argv[2]))
3065 UpdateServerThreadArgs threadArgs;
3066 threadArgs.argc = argc;
3067 threadArgs.argv =
const_cast<const NS_tchar**
>(argv);
3070 if (t1.Run(ServeElevatedUpdateThreadFunc, &threadArgs) == 0)
3087 LOG((
"failed setting status to 'applying'"));
3091 freeArguments(argc, argv);
3092 CleanupElevatedMacUpdate(
true);
3100 LOG((
"Performing a staged update"));
3104 LOG((
"Performing a replace request"));
3117 LOG((
"Installation directory and working directory must be the same "
3118 "for non-staged updates. Exiting."));
3125 sizeof(workingDirParent) /
sizeof(workingDirParent[0]),
3127 if (!PathRemoveFileSpecW(workingDirParent))
3130 LOG((
"Error calling PathRemoveFileSpecW: %d", GetLastError()));
3138 LOG((
"The apply-to directory must be the same as or "
3139 "a child of the installation directory! Exiting."));
3150 HANDLE parent = OpenProcess(SYNCHRONIZE,
false, (DWORD) pid);
3156 DWORD waitTime = PARENT_WAIT;
3157 DWORD
result = WaitForSingleObject(parent, waitTime);
3158 CloseHandle(parent);
3159 if (
result != WAIT_OBJECT_0)
3165 waitpid(pid,
nullptr, 0);
3169#ifdef MAINTENANCE_SERVICE
3171 putenv(
const_cast<char*
>(
"USING_SERVICE="));
3182 HANDLE updateLockFileHandle = INVALID_HANDLE_VALUE;
3193 sizeof(updateLockFilePath)/
sizeof(updateLockFilePath[0]),
3203 *slash =
NS_T(
'\0');
3205 sizeof(updateLockFilePath)/
sizeof(updateLockFilePath[0]),
3206 NS_T(
"%s\\moz_update_in_progress.lock"), installDir);
3213 sizeof(updateLockFilePath)/
sizeof(updateLockFilePath[0]),
3214 NS_T(
"%s.update_in_progress.lock"), argv[callbackIndex]);
3220 if (!_waccess(updateLockFilePath, F_OK) &&
3231 LOG((
"Update already in progress! Exiting"));
3235 updateLockFileHandle = CreateFileW(updateLockFilePath,
3236 GENERIC_READ | GENERIC_WRITE,
3240 FILE_FLAG_DELETE_ON_CLOSE,
3244 sizeof(elevatedLockFilePath)/
sizeof(elevatedLockFilePath[0]),
3248 bool startedFromUnelevatedUpdater =
3249 GetFileAttributesW(elevatedLockFilePath) != INVALID_FILE_ATTRIBUTES;
3257 if (startedFromUnelevatedUpdater)
3264 if (updateLockFileHandle == INVALID_HANDLE_VALUE ||
3265 (useService && testOnlyFallbackKeyExists && noServiceFallback))
3267 if (!_waccess(elevatedLockFilePath, F_OK) &&
3270 fprintf(stderr,
"Unable to create elevated lock file! Exiting\n");
3274 HANDLE elevatedFileHandle;
3275 elevatedFileHandle = CreateFileW(elevatedLockFilePath,
3276 GENERIC_READ | GENERIC_WRITE,
3280 FILE_FLAG_DELETE_ON_CLOSE,
3283 if (elevatedFileHandle == INVALID_HANDLE_VALUE)
3285 LOG((
"Unable to create elevated lock file! Exiting"));
3292 CloseHandle(elevatedFileHandle);
3302 useService =
IsLocalFile(argv[0], isLocal) && isLocal;
3313 BOOL unpromptedElevation;
3316 useService = !unpromptedElevation;
3324 WCHAR maintenanceServiceKey[
MAX_PATH + 1];
3328 maintenanceServiceKey))
3330 HKEY baseKey =
nullptr;
3331 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3332 maintenanceServiceKey, 0,
3333 KEY_READ | KEY_WOW64_64KEY,
3334 &baseKey) == ERROR_SUCCESS)
3336 RegCloseKey(baseKey);
3341 useService = testOnlyFallbackKeyExists;
3369 useService = (ret == ERROR_SUCCESS);
3373 bool showProgressUI =
false;
3380 showProgressUI = !InitProgressUIStrings();
3386 if (lastState != SERVICE_STOPPED)
3388 std::thread waitThread(WaitForServiceFinishThread,
nullptr);
3397 if (lastState != SERVICE_STOPPED)
3416 if (updateLockFileHandle != INVALID_HANDLE_VALUE)
3418 CloseHandle(updateLockFileHandle);
3433 bool updateStatusSucceeded =
false;
3434 if (IsUpdateStatusSucceeded(updateStatusSucceeded) &&
3435 updateStatusSucceeded)
3439 fprintf(stderr,
"The post update process which runs as the user"
3440 " for service update could not be launched.");
3451 if (!useService && !noServiceFallback &&
3452 updateLockFileHandle == INVALID_HANDLE_VALUE)
3454 SHELLEXECUTEINFO sinfo;
3455 memset(&sinfo, 0,
sizeof(SHELLEXECUTEINFO));
3456 sinfo.cbSize =
sizeof(SHELLEXECUTEINFO);
3457 sinfo.fMask = SEE_MASK_FLAG_NO_UI |
3458 SEE_MASK_FLAG_DDEWAIT |
3459 SEE_MASK_NOCLOSEPROCESS;
3460 sinfo.hwnd =
nullptr;
3461 sinfo.lpFile = argv[0];
3462 sinfo.lpParameters = cmdLine;
3463 sinfo.lpVerb = L
"runas";
3464 sinfo.nShow = SW_SHOWNORMAL;
3466 bool result = ShellExecuteEx(&sinfo);
3471 WaitForSingleObject(sinfo.hProcess, INFINITE);
3472 CloseHandle(sinfo.hProcess);
3480 if (argc > callbackIndex)
3486 CloseHandle(elevatedFileHandle);
3488 if (!useService && !noServiceFallback &&
3489 INVALID_HANDLE_VALUE == updateLockFileHandle)
3496 else if (useService)
3500 if (updateLockFileHandle != INVALID_HANDLE_VALUE)
3502 CloseHandle(updateLockFileHandle);
3513 CloseHandle(updateLockFileHandle);
3531 if (rv !=
OK && errno != EEXIST)
3536 freeArguments(argc, argv);
3537 CleanupElevatedMacUpdate(
true);
3567 gDestPath = destpath;
3572 sizeof(applyDirLongPath)/
sizeof(applyDirLongPath[0])))
3577 EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
3578 if (argc > callbackIndex)
3586 HANDLE callbackFile = INVALID_HANDLE_VALUE;
3587 if (argc > callbackIndex)
3595 ZeroMemory(callbackLongPath,
sizeof(callbackLongPath));
3596 NS_tchar *targetPath = argv[callbackIndex];
3603 size_t commonPrefixLength = PathCommonPrefixW(argv[callbackIndex],
3607 NS_tstrncpy(
p, argv[callbackIndex], commonPrefixLength);
3608 p += commonPrefixLength;
3609 bufferLeft -= commonPrefixLength;
3621 size_t callbackPrefixLength = PathCommonPrefixW(argv[callbackIndex],
3624 NS_tstrncpy(
p, argv[callbackIndex] + std::max(callbackPrefixLength,
3625 commonPrefixLength), bufferLeft);
3626 targetPath = buffer;
3628 if (!GetLongPathNameW(targetPath, callbackLongPath,
3629 sizeof(callbackLongPath)/
sizeof(callbackLongPath[0])))
3631 LOG((
"NS_main: unable to find callback file: " LOG_S, targetPath));
3634 EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
3635 if (argc > callbackIndex)
3638 argc - callbackIndex,
3639 argv + callbackIndex,
3654 if (*s ==
NS_T(
'\\'))
3661 if (*s ==
NS_T(
'\\'))
3674 sizeof(gCallbackBackupPath)/
sizeof(gCallbackBackupPath[0]),
3675 NS_T(
"%s" CALLBACK_BACKUP_EXT), argv[callbackIndex]);
3677 if (!CopyFileW(argv[callbackIndex], gCallbackBackupPath,
true))
3679 DWORD copyFileError = GetLastError();
3680 LOG((
"NS_main: failed to copy callback file " LOG_S
3681 " into place at " LOG_S, argv[callbackIndex], gCallbackBackupPath));
3683 if (copyFileError == ERROR_ACCESS_DENIED)
3692 EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
3694 argc - callbackIndex,
3695 argv + callbackIndex,
3704 const int max_retries = 10;
3706 DWORD lastWriteError = 0;
3712 callbackFile = CreateFileW(targetPath,
3715 FILE_SHARE_DELETE | FILE_SHARE_WRITE,
3716 nullptr, OPEN_EXISTING, 0,
nullptr);
3717 if (callbackFile != INVALID_HANDLE_VALUE)
3720 lastWriteError = GetLastError();
3721 LOG((
"NS_main: callback app file open attempt %d failed. " \
3722 "File: " LOG_S ". Last error: %d", retries,
3723 targetPath, lastWriteError));
3727 while (++retries <= max_retries);
3730 if (callbackFile == INVALID_HANDLE_VALUE)
3733 if (lastWriteError != ERROR_SHARING_VIOLATION)
3735 LOG((
"NS_main: callback app file in use, failed to exclusively open " \
3736 "executable file: " LOG_S, argv[callbackIndex]));
3738 if (lastWriteError == ERROR_ACCESS_DENIED)
3748 EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
3750 argc - callbackIndex,
3751 argv + callbackIndex,
3755 LOG((
"NS_main: callback app file in use, continuing without " \
3756 "exclusive access for executable file: " LOG_S,
3757 argv[callbackIndex]));
3775 sizeof(gDeleteDirPath) /
sizeof(gDeleteDirPath[0]),
3803 if (callbackFile != INVALID_HANDLE_VALUE)
3805 CloseHandle(callbackFile);
3813 LOG((
"NS_main: unable to remove directory: " LOG_S ", err: %d",
3814 DELETE_DIR, errno));
3824 if (MoveFileEx(gDeleteDirPath,
nullptr, MOVEFILE_DELAY_UNTIL_REBOOT))
3826 LOG((
"NS_main: directory will be removed on OS reboot: " LOG_S,
3831 LOG((
"NS_main: failed to schedule OS reboot removal of " \
3832 "directory: " LOG_S, DELETE_DIR));
3846 NS_tsnprintf(oldPrecomplete,
sizeof(oldPrecomplete)/
sizeof(oldPrecomplete[0]),
3851 NS_tsnprintf(oldDistDir,
sizeof(oldDistDir)/
sizeof(oldDistDir[0]),
3857 NS_tsnprintf(newDistDir,
sizeof(newDistDir)/
sizeof(newDistDir[0]),
3862 LOG((
"New distribution directory already exists... removing old " \
3863 "distribution directory: " LOG_S, oldDistDir));
3867 LOG((
"Removing old distribution directory failed - err: %d", rv));
3872 LOG((
"Moving old distribution directory to new location. src: " LOG_S \
3873 ", dst:" LOG_S, oldDistDir, newDistDir));
3877 LOG((
"Moving old distribution directory to new location failed - " \
3887 freeArguments(argc, argv);
3888 CleanupElevatedMacUpdate(
false);
3904 , elevatedLockFilePath
3905 , updateLockFileHandle
3906#elif defined(MACOSX)
3911 return retVal ? retVal : (
gSucceeded ? 0 : 1);
3962 LOG((
"empty action list"));
3970 int rv =
a->Prepare();
3986 int currentProgress = 0, maxProgress = 0;
3990 maxProgress +=
a->mProgressCost;
3997 int rv =
a->Execute();
4000 LOG((
"### execution failed"));
4004 currentProgress +=
a->mProgressCost;
4005 float percent = float(currentProgress) / float(maxProgress);
4041 WIN32_FIND_DATAW finddata;
4046 NS_tsnprintf(searchspec,
sizeof(searchspec)/
sizeof(searchspec[0]),
4047 NS_T(
"%s*"), dirpath);
4050 hFindFile = FindFirstFileW(pszSpec.get(), &finddata);
4051 if (hFindFile != INVALID_HANDLE_VALUE)
4060 NS_tsnprintf(foundpath,
sizeof(foundpath)/
sizeof(foundpath[0]),
4061 NS_T(
"%s%s"), dirpath, finddata.cFileName);
4062 if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
4064 NS_tsnprintf(foundpath,
sizeof(foundpath)/
sizeof(foundpath[0]),
4065 NS_T(
"%s/"), foundpath);
4070 LOG((
"add_dir_entries error: " LOG_S ", err: %d", foundpath, rv));
4082 rv =
action->Parse(quotedpath);
4085 LOG((
"add_dir_entries Parse error on recurse: " LOG_S ", err: %d",
4094 while (FindNextFileW(hFindFile, &finddata) != 0);
4096 FindClose(hFindFile);
4104 rv =
action->Parse(quotedpath);
4106 LOG((
"add_dir_entries Parse error on close: " LOG_S ", err: %d",
4125 char chars[MAXNAMLEN];
4130 DIR* dir = opendir(searchpath.get());
4133 LOG((
"add_dir_entries error on opendir: " LOG_S ", err: %d", searchpath.get(),
4138 while (readdir_r(dir, (dirent *)&ent_buf, &ent) == 0 && ent)
4140 if ((strcmp(ent->d_name,
".") == 0) ||
4141 (strcmp(ent->d_name,
"..") == 0))
4144 NS_tsnprintf(foundpath,
sizeof(foundpath)/
sizeof(foundpath[0]),
4145 NS_T(
"%s%s"), searchpath.get(), ent->d_name);
4146 struct stat64 st_buf;
4147 int test = stat64(foundpath, &st_buf);
4153 if (S_ISDIR(st_buf.st_mode))
4155 NS_tsnprintf(foundpath,
sizeof(foundpath)/
sizeof(foundpath[0]),
4156 NS_T(
"%s/"), foundpath);
4161 LOG((
"add_dir_entries error: " LOG_S ", err: %d", foundpath, rv));
4177 rv =
action->Parse(quotedpath);
4180 LOG((
"add_dir_entries Parse error on recurse: " LOG_S ", err: %d",
4197 rv =
action->Parse(quotedpath);
4200 LOG((
"add_dir_entries Parse error on close: " LOG_S ", err: %d",
4217 FTSENT *ftsdirEntry;
4223 char*
const pathargv[] = {searchpath.get(),
nullptr};
4227 if (!(ftsdir = fts_open(pathargv,
4228 FTS_PHYSICAL | FTS_NOSTAT | FTS_XDEV | FTS_NOCHDIR,
4232 while ((ftsdirEntry = fts_read(ftsdir)) !=
nullptr)
4238 switch (ftsdirEntry->fts_info)
4244 LOG((
"add_dir_entries: found a non-standard file: " LOG_S,
4245 ftsdirEntry->fts_path));
4252 NS_tsnprintf(foundpath,
sizeof(foundpath)/
sizeof(foundpath[0]),
4253 NS_T(
"%s"), ftsdirEntry->fts_accpath);
4261 rv =
action->Parse(quotedpath);
4271 NS_tsnprintf(foundpath,
sizeof(foundpath)/
sizeof(foundpath[0]),
4272 NS_T(
"%s/"), ftsdirEntry->fts_accpath);
4281 rv =
action->Parse(quotedpath);
4293 if (ENOENT == ftsdirEntry->fts_errno)
4302 LOG((
"add_dir_entries: fts_read() error: " LOG_S ", err: %d",
4303 ftsdirEntry->fts_path, ftsdirEntry->fts_errno));
4308 LOG((
"add_dir_entries: fts_read() returned FT_DC: " LOG_S,
4309 ftsdirEntry->fts_path));
4332 if (mfile ==
nullptr)
4334 LOG((
"GetManifestContents: error opening manifest file: " LOG_S, manifest));
4339 int rv = fstat(fileno((
FILE *)mfile), &ms);
4342 LOG((
"GetManifestContents: error stating manifest file: " LOG_S, manifest));
4346 char *mbuf = (
char *) malloc(ms.st_size + 1);
4350 size_t r = ms.st_size;
4355 size_t c = fread(rb, 1,
count, mfile);
4358 LOG((
"GetManifestContents: error reading manifest file: " LOG_S, manifest));
4366 mbuf[ms.st_size] =
'\0';
4379 if (!MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, rb, -1, wrb,
4382 LOG((
"GetManifestContents: error converting utf8 to utf16le: %d", GetLastError()));
4397 NS_T(
"Contents/Resources/precomplete")));
4400 NS_T(
"precomplete")));
4406 LOG((
"AddPreCompleteActions: error getting contents of precomplete " \
4424 LOG((
"AddPreCompleteActions: token not found in manifest"));
4443 LOG((
"AddPreCompleteActions: unknown token: " LOG_S, token));
4463 int nWrittenBytes =
NS_tsnprintf(manifest,
sizeof(manifest)/
sizeof(manifest[0]),
4465 (void) nWrittenBytes;
4471 int rv = archiveReader.
ExtractFile(
"updatev3.manifest", manifest);
4474 rv = archiveReader.
ExtractFile(
"updatev2.manifest", manifest);
4477 LOG((
"DoUpdate: error extracting manifest file"));
4486 LOG((
"DoUpdate: error opening manifest file: " LOG_S, manifest));
4492 bool isFirstAction =
true;
4503 LOG((
"DoUpdate: token not found in manifest"));
4509 isFirstAction =
false;
4572 LOG((
"DoUpdate: unknown token: " LOG_S, token));
int MBS_ApplyPatch(const MBSPatchHeader *header, FILE *patchFile, unsigned char *fbuffer, FILE *file)
Apply a patch.
int MBS_ReadHeader(FILE *file, MBSPatchHeader *header)
Read the header of a patch file into the MBSPatchHeader structure.
void Append(Action *action)
virtual int Parse(NS_tchar *line)=0
virtual void Finish(int status)=0
AddFile(ArchiveReader &ar)
virtual void Finish(int status)
ArchiveReader & mArchiveReader
virtual int Parse(NS_tchar *line)
std::unique_ptr< NS_tchar[]> mRelPath
std::unique_ptr< NS_tchar[]> mFile
virtual void Finish(int status)
std::unique_ptr< NS_tchar[]> mTestFile
virtual int Parse(NS_tchar *line)
AddIfFile(ArchiveReader &archiveReader)
virtual int Parse(NS_tchar *line)
AddIfNotFile(ArchiveReader &archiveReader)
virtual void Finish(int status)
std::unique_ptr< NS_tchar[]> mTestFile
int Open(const NS_tchar *path)
int ExtractFile(const char *item, const NS_tchar *destination)
int VerifySignature()
Performs a verification on the opened MAR file.
int ExtractFileToStream(const char *item, FILE *fp)
int VerifyProductInformation(const char *MARChannelID, const char *appVersion)
Verifies that the MAR file matches the current product, channel, and version.
AutoFile(FILE *file=nullptr)
AutoFile & operator=(FILE *file)
int LoadSourceFile(FILE *ofile)
virtual void Finish(int status)
virtual int Parse(NS_tchar *line)
std::unique_ptr< NS_tchar > mFileRelPath
PatchFile(ArchiveReader &ar)
NS_tchar spath[MAXPATHLEN]
ArchiveReader & mArchiveReader
std::unique_ptr< NS_tchar > mFile
const NS_tchar * mPatchFile
virtual void Finish(int status)
std::unique_ptr< NS_tchar[]> mTestFile
virtual int Parse(NS_tchar *line)
PatchIfFile(ArchiveReader &archiveReader)
virtual void Finish(int status)
virtual int Parse(NS_tchar *line)
std::unique_ptr< NS_tchar[]> mDir
std::unique_ptr< NS_tchar[]> mRelPath
std::unique_ptr< NS_tchar[]> mRelPath
std::unique_ptr< const NS_tchar[]> mFile
int Parse(NS_tchar *line)
static BOOL DisablePrivileges(HANDLE token)
#define WRITE_ERROR_CALLBACK_PATH
#define FALLBACKKEY_NOKEY_ERROR
#define WRITE_ERROR_FILE_ACCESS_DENIED
#define UNEXPECTED_FILE_OPERATION_ERROR
#define WRITE_ERROR_DIR_ACCESS_DENIED
#define DELETE_ERROR_EXPECTED_DIR
#define FALLBACKKEY_LAUNCH_ERROR
#define NO_INSTALLDIR_ERROR
#define LOADSOURCE_ERROR_WRONG_SIZE
#define DELETE_ERROR_EXPECTED_FILE
#define MAR_ERROR_EMPTY_ACTION_LIST
#define WRITE_ERROR_OPEN_PATCH_FILE
#define FALLBACKKEY_REGPATH_ERROR
#define UPDATER_MEM_ERROR
#define WRITE_ERROR_ACCESS_DENIED
#define UPDATER_QUOTED_PATH_MEM_ERROR
#define WRITE_ERROR_DELETE_BACKUP
#define STRING_CONVERSION_ERROR
#define WRITE_ERROR_DELETE_FILE
#define FALLBACKKEY_UNKNOWN_ERROR
#define WRITE_ERROR_FILE_COPY
#define WRITE_ERROR_CALLBACK_APP
#define ELEVATION_CANCELED
#define RENAME_ERROR_EXPECTED_FILE
#define WRITE_ERROR_APPLY_DIR_PATH
#define FALLBACKKEY_SERVICE_NO_STOP_ERROR
void LaunchChild(int argc, char **argv)
void LaunchMacPostProcess(const char *aAppBundle)
BOOL CalculateRegistryPathFromFilePath(const LPCWSTR filePath, LPWSTR registryPath)
Converts a file path into a unique registry location for cert storage.
int InitProgressUI(int *argc, char ***argv)
void UpdateProgressUI(float progress)
int ReadStrings(const NS_tchar *path, const char *keyList, unsigned int numStrings, char results[][MAX_TEXT_LEN], const char *section)
A very basic parser for updater.ini taken mostly from nsINIParser.cpp that can be used by standalone ...
const wchar_t *typedef BOOL
BOOL DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath)
Verifies if the file path matches any certificate stored in the registry.
BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra)
char MARChannelID[MAX_TEXT_LEN]
bool find(const NS_tchar *path)
void append(unsigned index, const NS_tchar *path, const NS_tchar *suffix)
void append(unsigned index, const NS_tchar *path)
NS_tchar paths[N][MAXPATHLEN]
unsigned _Unwind_Word __attribute__((__mode__(__word__)))
BOOL LaunchWinPostProcess(const WCHAR *installationDir, const WCHAR *updateInfoDir, bool forceSync, HANDLE userToken)
BOOL DoesFallbackKeyExist()
BOOL StartServiceUpdate(LPCWSTR installDir)
BOOL IsUnpromptedElevation(BOOL &isUnpromptedElevation)
BOOL IsLocalFile(LPCWSTR file, BOOL &isLocal)
DWORD WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds)
DWORD LaunchServiceSoftwareUpdateCommand(int argc, LPCWSTR *argv)
#define LogInit(PATHNAME_, FILENAME_)
static int ProcessReplaceRequest()
int add_dir_entries(const NS_tchar *dirpath, ActionList *list)
static int CopyInstallDirToDestDir()
static NS_tchar gWorkingDirPath[MAXPATHLEN]
static void backup_finish(const NS_tchar *path, const NS_tchar *relPath, int status)
static int ensure_copy_recursive(const NS_tchar *path, const NS_tchar *dest, copy_recursive_skiplist< N > &skiplist)
int AddPreCompleteActions(ActionList *list)
static NS_tchar * mstrtok(const NS_tchar *delims, NS_tchar **str)
static int ensure_parent_dir(const NS_tchar *path)
static const NS_tchar kNL[]
static void ensure_write_permissions(const NS_tchar *path)
static int ensure_copy(const NS_tchar *path, const NS_tchar *dest)
static NS_tchar * get_valid_path(NS_tchar **line, bool isdir=false)
Gets the platform specific path and performs simple checks to the path.
static NS_tchar * gPatchDirPath
static bool sReplaceRequest
static void UpdateThreadFunc(void *)
static NS_tchar gInstallDirPath[MAXPATHLEN]
static int CheckSignature(ArchiveReader &archiveReader)
int NS_main(int argc, NS_tchar **argv)
static bool is_read_only(const NS_tchar *flags)
static int ensure_remove(const NS_tchar *path)
static NS_tchar * get_quoted_path(const NS_tchar *path)
static int backup_restore(const NS_tchar *path, const NS_tchar *relPath)
#define PROGRESS_FINISH_SIZE
static int GetUpdateFileNames(std::vector< tstring > &fileNames)
static int DoUpdate(ArchiveReader &ArchiveReader)
static bool sStagedUpdate
#define PROGRESS_PREPARE_SIZE
static NS_tchar * new_absolute_path(const NS_tchar *relpath)
Converts a relative update path to an absolute path related to the working or install directory.
static const NS_tchar kQuote[]
static const NS_tchar * get_relative_offset(const NS_tchar *abs_path)
Get a pointer in the absolute path, relative to the working or install directory.
static int ensure_remove_recursive(const NS_tchar *path, bool continueEnumOnFailure=false)
#define PROGRESS_EXECUTE_SIZE
static void LaunchCallbackApp(const NS_tchar *workingDir, int argc, NS_tchar **argv, bool usingService)
static unsigned int crc32(const unsigned char *buf, unsigned int len)
static int backup_create(const NS_tchar *path)
static const NS_tchar kWhitespace[]
static bool WriteStatusFile(const char *aStatus)
int LaunchCallbackAndPostProcessApps(int argc, NS_tchar **argv, int callbackIndex)
static FILE * ensure_open(const NS_tchar *path, const NS_tchar *flags, unsigned int options)
static bool sUsingService
unsigned int BZ2_crc32Table[256]
static int ensure_copy_symlink(const NS_tchar *path, const NS_tchar *dest)
static int backup_discard(const NS_tchar *path, const NS_tchar *relPath)
static int rename_file(const NS_tchar *spath, const NS_tchar *dpath, bool allowDirs=false)
static NS_tchar * GetManifestContents(const NS_tchar *manifest)
BOOL WinLaunchChild(const wchar_t *exePath, int argc, wchar_t **argv, HANDLE userToken, HANDLE *hProcess)
BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath, LPCWSTR newFileName)
wchar_t * MakeCommandLine(int argc, wchar_t **argv)