blob: 9adf6e9c26f06125740790f5b87da0ebdc28eefd [file] [log] [blame]
// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos_update.h"
#include "chromeos/string.h"
#include <unistd.h>
#include <cstdlib>
#include <string>
#include <base/scoped_ptr.h>
#include <glib.h>
using std::string;
namespace chromeos {
namespace {
// This is the "virtualized" destructor for UpdateInformation.
void Destruct(const UpdateInformation& x) {
delete x.version_;
}
// Searches for a line "key=some value" for a given key 'key'
// and returns the value part of the line
string ValueForKey(const char* const haystack, const string& key) {
string use_key = key + "=";
const char* needle = NULL;
// See if haystack starts with key
if (!strncmp(haystack, use_key.data(), use_key.size())) {
needle = haystack;
} else {
use_key = string("\n") + use_key;
needle = strstr(haystack, use_key.c_str());
}
if (!needle)
return "";
needle += use_key.size();
const char* end = needle + 1;
while (*end != '\0' && *end != '\n') {
end++;
}
return string(needle, end - needle);
}
} // namespace
extern "C"
bool ChromeOSUpdate(UpdateInformation* information) {
scoped_array<char*> envp(new char*[2]);
envp[0] = strdup("PATH=/bin:/sbin:/usr/bin:/usr/sbin");
envp[1] = NULL;
scoped_array<char*> argv(new char*[3]);
argv[0] = strdup("/opt/google/memento_updater/suid_exec");
argv[1] = strdup("/opt/google/memento_updater/memento_updater.sh");
argv[2] = NULL;
gint exit_status = 0;
gchar* child_stdout = NULL;
GError* err = NULL;
gboolean success = g_spawn_sync(NULL, // Use parent's working dir
argv.get(),
envp.get(),
G_SPAWN_STDERR_TO_DEV_NULL, // no flags
NULL, // no setup function
NULL, // no setup function data
&child_stdout,
NULL, // stderr pointer
&exit_status,
&err);
if (!success || exit_status != 0) {
information->status_ = UPDATE_ERROR;
if (!success) {
information->version_ = NewStringCopy(err->message);
} else {
information->version_ = NewStringCopy("Nonzero return code");
}
return false;
}
if (child_stdout && !strcmp(child_stdout, "UPDATED")) {
information->status_ = UPDATE_SUCCESSFUL;
information->version_ = NewStringCopy("Updated to new version");
return true;
} else {
information->status_ = UPDATE_ERROR;
information->version_ = NewStringCopy("didn't update");
return false;
}
// TODO(adlr): handle up to date
//information->status_ = UPDATE_ALREADY_UP_TO_DATE;
//information->version_ = NewStringCopy("Didn't update");
}
extern "C"
bool ChromeOSCheckForUpdate(UpdateInformation* information) {
scoped_array<char*> envp(new char*[2]);
envp[0] = strdup("PATH=/bin:/sbin:/usr/bin:/usr/sbin");
envp[1] = NULL;
scoped_array<char*> argv(new char*[3]);
argv[0] = strdup("/opt/google/memento_updater/suid_exec");
argv[1] = strdup("/opt/google/memento_updater/ping_omaha.sh");
argv[2] = NULL;
gchar* child_stdout = NULL;
gint exit_status = 0;
GError* err = NULL;
gboolean success = g_spawn_sync(NULL, // Use parent's working dir
argv.get(),
envp.get(),
G_SPAWN_STDERR_TO_DEV_NULL, // flags
NULL, // no setup function
NULL, // no setup function data
&child_stdout,
NULL, // stderr pointer
&exit_status,
&err);
if (!success || exit_status != 0) {
information->status_ = UPDATE_ERROR;
if (!success) {
information->version_ = NewStringCopy(err->message);
} else {
information->version_ = NewStringCopy("Nonzero return code");
}
return false;
}
if (strlen(child_stdout) > 0) {
string new_version = ValueForKey(child_stdout, "NEW_VERSION");
information->status_ = UPDATE_IS_AVAILABLE;
information->version_ = NewStringCopy(new_version.c_str());
} else {
information->status_ = UPDATE_ALREADY_UP_TO_DATE;
information->version_ = NewStringCopy("No new version");
}
return true;
}
} // namespace chromeos