diff options
Diffstat (limited to 'indra/viewer_components')
8 files changed, 345 insertions, 112 deletions
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index d480b63094..bdcb068200 100644 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -271,6 +271,16 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_para } return; // Done! } + + /* Sometimes we end with "Started" here. Slightly slow server? + * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below. + */ + if( status == "Started") + { + LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL; + continue; + } + // If we don't recognize status at all, trouble if (! (status == "CURLError" || status == "XMLRPCError" diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index c6aa9b0f11..5edbbf9914 100644 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -30,7 +30,9 @@ #include "llsd.h" #include "llupdatechecker.h" #include "lluri.h" - +#if LL_DARWIN +#include <CoreServices/CoreServices.h> +#endif #if LL_WINDOWS #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally @@ -49,37 +51,6 @@ public: }; -class LLUpdateChecker::Implementation: - public LLHTTPClient::Responder -{ -public: - Implementation(Client & client); - ~Implementation(); - void check(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version); - - // Responder: - virtual void completed(U32 status, - const std::string & reason, - const LLSD& content); - virtual void error(U32 status, const std::string & reason); - -private: - static const char * sProtocolVersion; - - Client & mClient; - LLHTTPClient mHttpClient; - bool mInProgress; - std::string mVersion; - - std::string buildUrl(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version); - - LOG_CLASS(LLUpdateChecker::Implementation); -}; - - - // LLUpdateChecker //----------------------------------------------------------------------------- @@ -91,10 +62,10 @@ LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client): } -void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl, +void LLUpdateChecker::checkVersion(std::string const & protocolVersion, std::string const & hostUrl, std::string const & servicePath, std::string channel, std::string version) { - mImplementation->check(protocolVersion, hostUrl, servicePath, channel, version); + mImplementation->checkVersion(protocolVersion, hostUrl, servicePath, channel, version); } @@ -120,7 +91,7 @@ LLUpdateChecker::Implementation::~Implementation() } -void LLUpdateChecker::Implementation::check(std::string const & protocolVersion, std::string const & hostUrl, +void LLUpdateChecker::Implementation::checkVersion(std::string const & protocolVersion, std::string const & hostUrl, std::string const & servicePath, std::string channel, std::string version) { llassert(!mInProgress); @@ -132,13 +103,7 @@ void LLUpdateChecker::Implementation::check(std::string const & protocolVersion, std::string checkUrl = buildUrl(protocolVersion, hostUrl, servicePath, channel, version); LL_INFOS("UpdateCheck") << "checking for updates at " << checkUrl << llendl; - // The HTTP client will wrap a raw pointer in a boost::intrusive_ptr causing the - // passed object to be silently and automatically deleted. We pass a self- - // referential intrusive pointer to which we add a reference to keep the - // client from deleting the update checker implementation instance. - LLHTTPClient::ResponderPtr temporaryPtr(this); - boost::intrusive_ptr_add_ref(temporaryPtr.get()); - mHttpClient.get(checkUrl, temporaryPtr); + mHttpClient.get(checkUrl, this); } void LLUpdateChecker::Implementation::completed(U32 status, @@ -179,7 +144,18 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & protoc #ifdef LL_WINDOWS static const char * platform = "win"; #elif LL_DARWIN - static const char * platform = "mac"; + long versMin; + Gestalt(gestaltSystemVersionMinor, &versMin); + + static const char *platform; + if (versMin == 5) //OS 10.5 + { + platform = "mac_legacy"; + } + else + { + platform = "mac"; + } #else static const char * platform = "lnx"; #endif diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h index cea1f13647..23f62a7c5e 100644 --- a/indra/viewer_components/updater/llupdatechecker.h +++ b/indra/viewer_components/updater/llupdatechecker.h @@ -29,6 +29,7 @@ #include <boost/shared_ptr.hpp> +#include "llhttpclient.h" // // Implements asynchronous checking for updates. @@ -36,7 +37,36 @@ class LLUpdateChecker { public: class Client; - class Implementation; + class Implementation: + + public LLHTTPClient::Responder + { + public: + Implementation(Client & client); + ~Implementation(); + void checkVersion(std::string const & protocolVersion, std::string const & hostUrl, + std::string const & servicePath, std::string channel, std::string version); + + // Responder: + virtual void completed(U32 status, + const std::string & reason, + const LLSD& content); + virtual void error(U32 status, const std::string & reason); + + private: + static const char * sProtocolVersion; + + Client & mClient; + LLHTTPClient mHttpClient; + bool mInProgress; + std::string mVersion; + + std::string buildUrl(std::string const & protocolVersion, std::string const & hostUrl, + std::string const & servicePath, std::string channel, std::string version); + + LOG_CLASS(LLUpdateChecker::Implementation); + }; + // An exception that may be raised on check errors. class CheckError; @@ -44,11 +74,11 @@ public: LLUpdateChecker(Client & client); // Check status of current app on the given host for the channel and version provided. - void check(std::string const & protocolVersion, std::string const & hostUrl, + void checkVersion(std::string const & protocolVersion, std::string const & hostUrl, std::string const & servicePath, std::string channel, std::string version); private: - boost::shared_ptr<Implementation> mImplementation; + LLPointer<Implementation> mImplementation; }; diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index e88d1bf811..75e455e3f6 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -1,24 +1,24 @@ -/** +/** * @file llupdatedownloader.cpp * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -39,7 +39,7 @@ #include "llsdserialize.h" #include "llthread.h" #include "llupdaterservice.h" - +#include "llcurl.h" class LLUpdateDownloader::Implementation: public LLThread @@ -58,7 +58,7 @@ public: int onProgress(double downloadSize, double bytesDownloaded); void resume(void); void setBandwidthLimit(U64 bytesPerSecond); - + private: curl_off_t mBandwidthLimit; bool mCancelled; @@ -69,7 +69,7 @@ private: unsigned char mDownloadPercent; std::string mDownloadRecordPath; curl_slist * mHeaderList; - + void initializeCurlGet(std::string const & url, bool processHeader); void resumeDownloading(size_t startByte); void run(void); @@ -93,7 +93,7 @@ namespace { } }; - + const char * gSecondLifeUpdateRecord = "SecondLifeUpdateDownload.xml"; }; @@ -192,19 +192,25 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & mHeaderList(0) { CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case. - llverify(code == CURLE_OK); // TODO: real error handling here. + llverify(code == CURLE_OK); // TODO: real error handling here. } LLUpdateDownloader::Implementation::~Implementation() { - if(isDownloading()) { + if(isDownloading()) + { cancel(); shutdown(); - } else { + } + else + { ; // No op. } - if(mCurl) curl_easy_cleanup(mCurl); + if(mCurl) + { + LLCurl::deleteEasyHandle(mCurl); + } } @@ -212,7 +218,7 @@ void LLUpdateDownloader::Implementation::cancel(void) { mCancelled = true; } - + void LLUpdateDownloader::Implementation::download(LLURI const & uri, std::string const & hash, @@ -253,24 +259,24 @@ void LLUpdateDownloader::Implementation::resume(void) mClient.downloadError("no download marker"); return; } - + LLSDSerialize::fromXMLDocument(mDownloadData, dataStream); - + if(!mDownloadData.asBoolean()) { mClient.downloadError("no download information in marker"); return; } - + std::string filePath = mDownloadData["path"].asString(); try { - if(LLFile::isfile(filePath)) { + if(LLFile::isfile(filePath)) { llstat fileStatus; LLFile::stat(filePath, &fileStatus); if(fileStatus.st_size != mDownloadData["size"].asInteger()) { resumeDownloading(fileStatus.st_size); } else if(!validateDownload()) { LLFile::remove(filePath); - download(LLURI(mDownloadData["url"].asString()), + download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString(), mDownloadData["update_version"].asString(), mDownloadData["required"].asBoolean()); @@ -278,7 +284,7 @@ void LLUpdateDownloader::Implementation::resume(void) mClient.downloadComplete(mDownloadData); } } else { - download(LLURI(mDownloadData["url"].asString()), + download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString(), mDownloadData["update_version"].asString(), mDownloadData["required"].asBoolean()); @@ -295,7 +301,7 @@ void LLUpdateDownloader::Implementation::setBandwidthLimit(U64 bytesPerSecond) llassert(mCurl != 0); mBandwidthLimit = bytesPerSecond; CURLcode code = curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit); - if(code != CURLE_OK) LL_WARNS("UpdateDownload") << + if(code != CURLE_OK) LL_WARNS("UpdateDownload") << "unable to change dowload bandwidth" << LL_ENDL; } else { mBandwidthLimit = bytesPerSecond; @@ -309,7 +315,7 @@ size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) std::string header(headerPtr, headerPtr + size); size_t colonPosition = header.find(':'); if(colonPosition == std::string::npos) return size; // HTML response; ignore. - + if(header.substr(0, colonPosition) == "Content-Length") { try { size_t firstDigitPos = header.find_first_of("0123456789", colonPosition); @@ -317,18 +323,18 @@ size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) std::string contentLength = header.substr(firstDigitPos, lastDigitPos - firstDigitPos + 1); size_t size = boost::lexical_cast<size_t>(contentLength); LL_INFOS("UpdateDownload") << "download size is " << size << LL_ENDL; - + mDownloadData["size"] = LLSD(LLSD::Integer(size)); llofstream odataStream(mDownloadRecordPath); LLSDSerialize::toPrettyXML(mDownloadData, odataStream); } catch (std::exception const & e) { - LL_WARNS("UpdateDownload") << "unable to read content length (" + LL_WARNS("UpdateDownload") << "unable to read content length (" << e.what() << ")" << LL_ENDL; } } else { ; // No op. } - + return size; } @@ -336,9 +342,9 @@ size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) size_t LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size) { if(mCancelled) return 0; // Forces a write error which will halt curl thread. - if((size == 0) || (buffer == 0)) return 0; - - mDownloadStream.write(reinterpret_cast<const char *>(buffer), size); + if((size == 0) || (buffer == 0)) return 0; + + mDownloadStream.write(static_cast<const char *>(buffer), size); if(mDownloadStream.bad()) { return 0; } else { @@ -352,7 +358,7 @@ int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double b int downloadPercent = static_cast<int>(100. * (bytesDownloaded / downloadSize)); if(downloadPercent > mDownloadPercent) { mDownloadPercent = downloadPercent; - + LLSD event; event["pump"] = LLUpdaterService::pumpName(); LLSD payload; @@ -361,12 +367,12 @@ int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double b payload["bytes_downloaded"] = bytesDownloaded; event["payload"] = payload; LLEventPumps::instance().obtain("mainlooprepeater").post(event); - + LL_INFOS("UpdateDownload") << "progress event " << payload << LL_ENDL; } else { ; // Keep events to a reasonalbe number. } - + return 0; } @@ -390,13 +396,13 @@ void LLUpdateDownloader::Implementation::run(void) LL_INFOS("UpdateDownload") << "download canceled by user" << LL_ENDL; // Do not call back client. } else { - LL_WARNS("UpdateDownload") << "download failed with error '" << + LL_WARNS("UpdateDownload") << "download failed with error '" << curl_easy_strerror(code) << "'" << LL_ENDL; LLFile::remove(mDownloadRecordPath); if(mDownloadData.has("path")) LLFile::remove(mDownloadData["path"].asString()); mClient.downloadError("curl error"); } - + if(mHeaderList) { curl_slist_free_all(mHeaderList); mHeaderList = 0; @@ -406,14 +412,17 @@ void LLUpdateDownloader::Implementation::run(void) void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader) { - if(mCurl == 0) { - mCurl = curl_easy_init(); - } else { + if(mCurl == 0) + { + mCurl = LLCurl::newEasyHandle(); + } + else + { curl_easy_reset(mCurl); } - + if(mCurl == 0) throw DownloadError("failed to initialize curl"); - + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, true)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, true)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function)); @@ -430,7 +439,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u // if it's a required update set the bandwidth limit to 0 (unlimited) curl_off_t limit = mDownloadData["required"].asBoolean() ? 0 : mBandwidthLimit; throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, limit)); - + mDownloadPercent = 0; } @@ -441,7 +450,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte) << " at byte " << startByte << LL_ENDL; initializeCurlGet(mDownloadData["url"].asString(), false); - + // The header 'Range: bytes n-' will request the bytes remaining in the // source begining with byte n and ending with the last byte. boost::format rangeHeaderFormat("Range: bytes=%u-"); @@ -449,7 +458,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte) mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str()); if(mHeaderList == 0) throw DownloadError("cannot add Range header"); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, mHeaderList)); - + mDownloadStream.open(mDownloadData["path"].asString(), std::ios_base::out | std::ios_base::binary | std::ios_base::app); start(); @@ -470,10 +479,10 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std LL_INFOS("UpdateDownload") << "downloading " << filePath << " from " << uri.asString() << LL_ENDL; LL_INFOS("UpdateDownload") << "hash of file is " << hash << LL_ENDL; - + llofstream dataStream(mDownloadRecordPath); LLSDSerialize::toPrettyXML(mDownloadData, dataStream); - + mDownloadStream.open(filePath, std::ios_base::out | std::ios_base::binary); initializeCurlGet(uri.asString(), true); start(); diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp index c7b70c2de8..2f87d59373 100644 --- a/indra/viewer_components/updater/llupdateinstaller.cpp +++ b/indra/viewer_components/updater/llupdateinstaller.cpp @@ -26,10 +26,10 @@ #include "linden_common.h" #include <apr_file_io.h> #include "llapr.h" -#include "llprocesslauncher.h" +#include "llprocess.h" #include "llupdateinstaller.h" #include "lldir.h" - +#include "llsd.h" #if defined(LL_WINDOWS) #pragma warning(disable: 4702) // disable 'unreachable code' so we can use lexical_cast (really!). @@ -78,15 +78,13 @@ int ll_install_update(std::string const & script, llinfos << "UpdateInstaller: installing " << updatePath << " using " << actualScriptPath << LL_ENDL; - LLProcessLauncher launcher; - launcher.setExecutable(actualScriptPath); - launcher.addArgument(updatePath); - launcher.addArgument(ll_install_failed_marker_path().c_str()); - launcher.addArgument(boost::lexical_cast<std::string>(required)); - int result = launcher.launch(); - launcher.orphan(); - - return result; + LLProcess::Params params; + params.executable = actualScriptPath; + params.args.add(updatePath); + params.args.add(ll_install_failed_marker_path()); + params.args.add(boost::lexical_cast<std::string>(required)); + params.autokill = false; + return LLProcess::create(params)? 0 : -1; } diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 1888f191e2..bc73c72ddc 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -447,7 +447,7 @@ void LLUpdaterServiceImpl::restartTimer(unsigned int seconds) LL_INFOS("UpdaterService") << "will check for update again in " << seconds << " seconds" << LL_ENDL; mTimer.start(); - mTimer.setTimerExpirySec(seconds); + mTimer.setTimerExpirySec((F32)seconds); LLEventPumps::instance().obtain("mainloop").listen( sListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1)); } @@ -509,7 +509,7 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event) } else { - mUpdateChecker.check(mProtocolVersion, mUrl, mPath, mChannel, mVersion); + mUpdateChecker.checkVersion(mProtocolVersion, mUrl, mPath, mChannel, mVersion); setState(LLUpdaterService::CHECKING_FOR_UPDATE); } } diff --git a/indra/viewer_components/updater/scripts/linux/update_install b/indra/viewer_components/updater/scripts/linux/update_install index e0505a9f72..a9df9042fd 100644 --- a/indra/viewer_components/updater/scripts/linux/update_install +++ b/indra/viewer_components/updater/scripts/linux/update_install @@ -1,10 +1,217 @@ #! /bin/bash -INSTALL_DIR=$(cd "$(dirname "$0")/.." ; pwd) -export LD_LIBRARY_PATH="$INSTALL_DIR/lib" -bin/linux-updater.bin --file "$1" --dest "$INSTALL_DIR" --name "Second Life Viewer" --stringsdir "$INSTALL_DIR/skins/default/xui/en" --stringsfile "strings.xml" -if [ $? -ne 0 ] - then echo $3 >> "$2" +# @file update_install +# @author Nat Goodspeed +# @date 2013-01-09 +# @brief Update the containing Second Life application bundle to the version in +# the specified tarball. +# +# This bash implementation is derived from the previous linux-updater.bin +# application. +# +# $LicenseInfo:firstyear=2013&license=viewerlgpl$ +# Copyright (c) 2013, Linden Research, Inc. +# $/LicenseInfo$ + +# **************************************************************************** +# script parameters +# **************************************************************************** +tarball="$1" # the file to install +markerfile="$2" # create this file on failure +mandatory="$3" # what to write to markerfile on failure + +# **************************************************************************** +# helper functions +# **************************************************************************** +# empty array +cleanups=() + +# add a cleanup action to execute on exit +function cleanup { + # wacky bash syntax for appending to array + cleanups[${#cleanups[*]}]="$*" +} + +# called implicitly on exit +function onexit { + for action in "${cleanups[@]}" + do # don't quote, support actions consisting of multiple words + $action + done +} +trap 'onexit' EXIT + +# write to log file +function log { + # our log file will be open as stderr -- but until we set up that + # redirection, logging to stderr is better than nothing + echo "$*" 1>&2 +} + +# We display status by leaving one background xmessage process running. This +# is the pid of that process. +statuspid="" + +function clear_message { + [ -n "$statuspid" ] && kill $statuspid + statuspid="" +} + +# make sure we remove any message box we might have put up +cleanup clear_message + +# can we use zenity, or must we fall back to xmessage? +zenpath="$(which zenity)" +if [ -n "$zenpath" ] +then # zenity on PATH and is executable + # display a message box and continue + function status { + # clear any previous message + clear_message + # put up a new zenity box and capture its pid + "$zenpath" --info --title "Second Life Viewer Updater" \ + --width=320 --height=120 --text="$*" & + statuspid=$! + } + + # display an error box and wait for user + function errorbox { + "$zenpath" --error --title "Second Life Viewer Updater" \ + --width=320 --height=120 --text="$*" + } + +else # no zenity, use xmessage instead + # display a message box and continue + function status { + # clear any previous message + clear_message + # put up a new xmessage and capture its pid + xmessage -buttons OK:2 -center "$*" & + statuspid=$! + } + + # display an error box and wait for user + function errorbox { + xmessage -buttons OK:2 -center "$*" + } +fi + +# display an error box and terminate +function fail { + # Log the message + log "$@" + # tell subsequent viewer things went south + echo "$mandatory" > "$markerfile" + # add boilerplate + errorbox "An error occurred while updating Second Life: +$* +Please download the latest viewer from www.secondlife.com." + exit 1 +} + +# Find a graphical sudo program and define mysudo function. On error, $? is +# nonzero; output is in $err instead of being written to stdout/stderr. +gksudo="$(which gksudo)" +kdesu="$(which kdesu)" +if [ -n "$gksudo" ] +then function mysudo { + # gksudo allows you to specify description + err="$("$gksudo" --description "Second Life Viewer Updater" "$@" 2>&1)" + } +elif [ -n "$kdesu" ] +then function mysudo { + err="$("$kdesu" "$@" 2>&1)" + } +else # couldn't find either one, just try it anyway + function mysudo { + err="$("$@" 2>&1)" + } fi -rm -f "$1" +# Move directories, using mysudo if we think it necessary. On error, $? is +# nonzero; output is in $err instead of being written to stdout/stderr. +function sudo_mv { + # If we have write permission to both parent directories, shouldn't need + # sudo. + if [ -w "$(dirname "$1")" -a -w "$(dirname "$2")" ] + then err="$(mv "$@" 2>&1)" + else # use available sudo program; mysudo sets $? and $err + mysudo mv "$@" + fi +} + +# **************************************************************************** +# main script logic +# **************************************************************************** +mydir="$(dirname "$0")" +# We happen to know that the viewer specifies a marker-file pathname within +# the logs directory. +logsdir="$(dirname "$markerfile")" +logname="$logsdir/updater.log" + +# move aside old updater.log; we're about to create a new one +[ -f "$logname" ] && mv "$logname" "$logname.old" + +# Set up redirections for this script such that stderr is logged. (But first +# move the previous stderr to file descriptor 3.) +exec 3>&2- 2> "$logname" + +# Rather than setting up a special pipeline to timestamp every line of stderr, +# produce header lines into log file indicating timestamp and the arguments +# with which we were invoked. +date 1>&2 +log "$0 $*" + +# Log every command we execute, along with any stderr it might produce +set -x + +status 'Installing Second Life...' + +# Creating tempdir under /tmp means it's possible that tempdir is on a +# different filesystem than INSTALL_DIR. One is tempted to create tempdir on a +# path derived from `dirname INSTALL_DIR` -- but it seems modern 'mv' can +# handle moving across filesystems?? +tempdir="$(mktemp -d)" +tempinstall="$tempdir/install" +# capture the actual error message, if any +err="$(mkdir -p "$tempinstall" 2>&1)" || fail "$err" +cleanup rm -rf "$tempdir" + +# If we already knew the name of the tarball's top-level directory, we could +# just move that when all was said and done. Since we don't, untarring to the +# 'install' subdir with --strip 1 effectively renames that top-level +# directory. +# untar failures tend to be voluminous -- don't even try to capture, just log +tar --strip 1 -xjf "$tarball" -C "$tempinstall" || fail "Untar command failed" + +INSTALL_DIR="$(cd "$mydir/.." ; pwd)" + +# Considering we're launched from a subdirectory of INSTALL_DIR, would be +# surprising if it did NOT already exist... +if [ -e "$INSTALL_DIR" ] +then backup="$INSTALL_DIR.backup" + backupn=1 + while [ -e "$backup" ] + do backup="$INSTALL_DIR.backup.$backupn" + ((backupn += 1)) + done + # on error, fail with actual error message from sudo_mv: permissions, + # cross-filesystem mv, ...? + sudo_mv "$INSTALL_DIR" "$backup" || fail "$err" +fi +# We unpacked the tarball into tempinstall. Move that. +if ! sudo_mv "$tempinstall" "$INSTALL_DIR" +then # If we failed to move the temp install to INSTALL_DIR, try to restore + # INSTALL_DIR from backup. Save $err because next sudo_mv will trash it! + realerr="$err" + sudo_mv "$backup" "$INSTALL_DIR" + fail "$realerr" +fi + +# Removing the tarball here, rather than with a 'cleanup' action, means we +# only remove it if we succeeded. +rm -f "$tarball" + +# Launch the updated viewer. Restore original stderr from file descriptor 3, +# though -- otherwise updater.log gets cluttered with the viewer log! +"$INSTALL_DIR/secondlife" 2>&3- & diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index e19d5724f1..de07beee7c 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llupdaterservice_test.cpp * @brief Tests of llupdaterservice.cpp. * @@ -44,7 +44,7 @@ *****************************************************************************/ LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client) {} -void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl, +void LLUpdateChecker::checkVersion(std::string const & protocolVersion, std::string const & hostUrl, std::string const & servicePath, std::string channel, std::string version) {} LLUpdateDownloader::LLUpdateDownloader(Client & ) {} @@ -63,7 +63,7 @@ class LLDir_Mock : public LLDir const std::string &mask, std::string &fname) {} std::string getCurPath() { return ""; } - BOOL fileExists(const std::string &filename) const { return false; } + bool fileExists(const std::string &filename) const { return false; } std::string getLLPluginLauncher() { return ""; } std::string getLLPluginFilename(std::string base_name) { return ""; } @@ -78,9 +78,12 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, void LLDir::setChatLogsDir(const std::string &path){} void LLDir::setPerAccountChatLogsDir(const std::string &username){} void LLDir::setLindenUserDir(const std::string &username){} -void LLDir::setSkinFolder(const std::string &skin_folder){} +void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language){} +std::string LLDir::getSkinFolder() const { return "default"; } +std::string LLDir::getLanguage() const { return "en"; } bool LLDir::setCacheDir(const std::string &path){ return true; } void LLDir::dumpCurrentDirectories() {} +void LLDir::updatePerAccountChatLogsDir() {} std::string LLDir::getExpandedFilename(ELLPath location, const std::string &filename) const |