summaryrefslogtreecommitdiff
path: root/src/factory-reset.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/factory-reset.c')
-rw-r--r--src/factory-reset.c341
1 files changed, 341 insertions, 0 deletions
diff --git a/src/factory-reset.c b/src/factory-reset.c
new file mode 100644
index 0000000..a0de792
--- /dev/null
+++ b/src/factory-reset.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd.
+ *
+ * Contact: MyoungJune Park <mj2004.park@samsung.com>
+ * Created by Wonil Choi <wonil22.choi@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <linux/reboot.h>
+#include <linux/limits.h>
+#include <sys/reboot.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <time.h>
+#include <getopt.h>
+#include <dbus/dbus.h>
+#include <glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#define RESET_FLAG_FILE "/opt/.factoryreset"
+static const char RESET_BACKUP_FILE[2][40] = {
+ "/usr/system/RestoreDir/opt.tar.gz",
+ "/usr/system/RestoreDir/opt.zip"
+};
+
+static const char *RUN_SCRIPT_FILE = "/usr/bin/run-factory-reset.sh";
+static const char *LOG_FILE = "/opt/.factoryreset.log";
+static const char *LOG_OLD = "/opt/.factoryreset.log.1";
+
+static char *reset_flag;
+
+void usage()
+{
+ printf("Options: \n");
+ printf(" -b, --dbus Start with dbus signal message\n");
+ printf("\n");
+
+ exit(0);
+}
+
+//extern int csc_svc_config_set_pre_config_for_factory_reset( void );
+/*==================================================================================
+* CSC API Code (12/10/11 applied)
+ - Include header : #include "csc-dispatch.h"
+ - API : int csc_svc_config_set_pre_config_for_factory_reset( void );
+ - Return value : 1 (Success), 0 (Failure, 미리 저장해놓은 거래선 코드가 없을 경우 발생)
+====================================================================================*/
+int __system(const char *argv[])
+{
+ int status;
+ pid_t cpid;
+
+ cpid = fork();
+
+ if (cpid == -1) {
+ perror("fork");
+ return -1;
+ }
+
+ if (cpid == 0) {
+ execvp(argv[0], (char *const *)argv);
+ _exit(-1);
+ } else {
+ if (waitpid(cpid, &status, 0) == -1) {
+ perror("waitpid failed");
+ return -1;
+ }
+ if (WIFSIGNALED(status)) {
+ perror("exit by signal");
+ return -1;
+ }
+ if (!WIFEXITED(status)) {
+ perror("exit abnormally");
+ return -1;
+ }
+ if (WIFEXITED(status) && WEXITSTATUS(status)) {
+ perror("child return error");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+#define RESET_DBUS_SERVICE "org.tizen.factoryreset"
+#define RESET_DBUS_INTERFACE RESET_DBUS_SERVICE".start"
+
+static const char granted_caller[6][16] = {
+ "setting",
+ "cscmgr",
+ "wms",
+ "bt", /* when the host device is changed */
+ "omadmagent",
+ "testmode"
+};
+
+static const char list_reset_flags[2][16] = {
+ "ftrrstcp",
+ "withoutcp"
+};
+
+
+static GMainLoop* loop;
+static DBusConnection *bus_conn = NULL;
+static const char *dbus_obj_path = "/org/tizen/factoryreset";
+
+static void unregistered_func (DBusConnection *connection, void *user_data)
+{
+ perror("factory-reset dbus unregistered\n");
+}
+
+static DBusHandlerResult message_func (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ /* store the name of factory reset caller. */
+ char caller_name[NAME_MAX];
+ FILE *fp = NULL;
+ int i = 0;
+
+ if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL) {
+ perror("Not a dbus-signal\n");
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ if (strncmp(dbus_message_get_interface(message), RESET_DBUS_INTERFACE,
+ strlen(RESET_DBUS_INTERFACE)) != 0) {
+ printf("Not correct interface: \"%s\"\n",
+ dbus_message_get_interface (message));
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ strncpy(caller_name, dbus_message_get_member(message),
+ sizeof(caller_name));
+ caller_name[NAME_MAX - 1] = '\0';
+
+ while (strncmp(granted_caller[i], caller_name,
+ strlen(granted_caller[i]))) {
+ if ((++i) >= sizeof(granted_caller) / sizeof(granted_caller[0])) {
+ printf("Not a granted caller, %s\n", caller_name);
+ /* XXX Warning: Comparing granted caller list cannot
+ * grant good caller or not. Security is and should be
+ * protected by the SMACK rule. This code is only for
+ * preventing that a new unknown caller use factory
+ * reset without confirmation of the factory reset
+ * developer.
+ */
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ }
+ fp = fopen(LOG_FILE, "a");
+ if (fp != NULL) {
+ fprintf(fp, "Requested by %s, %s\n", caller_name,
+ dbus_message_get_sender(message));
+ fclose(fp);
+ }
+
+ /* member name of dbus signal message may contains reset flags */
+ for (i = 0; i < sizeof(list_reset_flags) / sizeof(list_reset_flags[0]);
+ i++) {
+ if (strstr(caller_name, list_reset_flags[i])) {
+ snprintf(caller_name, NAME_MAX, "--%s",
+ list_reset_flags[i]);
+ reset_flag = strdup(caller_name);
+ break;
+ }
+ }
+
+ g_main_loop_quit(loop);
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+
+static DBusHandlerResult filter_func (DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL,
+ "Disconnected")) {
+ /* Exit cleanly. */
+ printf("Disconnected");
+ }
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusObjectPathVTable dbus_vtable = {
+ unregistered_func,
+ message_func,
+ NULL,
+};
+
+static int process_dbus(void)
+{
+ int ret;
+ DBusError error;
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ dbus_error_init (&error);
+ bus_conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ if (!bus_conn) {
+ perror("failed to get dbus system bus");
+ dbus_error_free(&error);
+ return -1;
+ }
+ /* Add message filter to handle Disconnected. */
+ dbus_connection_add_filter(bus_conn, (DBusHandleMessageFunction) filter_func,
+ NULL, NULL);
+
+ ret = dbus_bus_request_name(bus_conn, RESET_DBUS_SERVICE, 0, &error);
+
+ /* Should be ret == -1, if error is set */
+ if (ret == -1 && dbus_error_is_set(&error)) {
+ dbus_error_free (&error);
+ return -1;
+ }
+
+ if (!dbus_connection_register_object_path(bus_conn, dbus_obj_path,
+ &dbus_vtable, NULL)) {
+ return -1;
+ }
+
+ dbus_connection_setup_with_g_main(bus_conn, NULL);
+ g_main_loop_run(loop);
+ return 0;
+}
+
+
+int main(int argc, char **argv)
+{
+ FILE *fp;
+ int ret, i = 0, c;
+ const char *reset_cmd[] = {RUN_SCRIPT_FILE, NULL, NULL};
+ time_t t = time(NULL);
+ struct tm tm2 = *localtime(&t);
+
+ static struct option long_options[] = {
+ {"dbus", no_argument, NULL, 'b'},
+ {0, 0, 0, 0}
+ };
+
+ ret = setuid(0);
+ if (ret < 0) {
+ perror("wrong permission");
+ return -1;
+ }
+
+ /* If there is no factory-reset backup file, don't try to reset. */
+ while (!(fp = fopen(RESET_BACKUP_FILE[i++], "r"))) {
+ if (i >= sizeof(RESET_BACKUP_FILE) /
+ sizeof(RESET_BACKUP_FILE[0])) {
+ perror("backup file is not exist");
+ return -1;
+ }
+ }
+ if (fp != NULL) fclose(fp);
+
+ if (rename(LOG_FILE, LOG_OLD) < 0)
+ perror("can't rename the old log file");
+
+ while (1) {
+
+ int option_index = -1;
+ c = getopt_long(argc, argv, "b", long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'b':
+
+ if (process_dbus() < 0) {
+ perror("dbus has some errors.");
+ return -1;
+ }
+ break;
+
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (optind < argc)
+ usage();
+
+#if 0
+ fp = fopen(RESET_FLAG_FILE, "w");
+ if (fp == NULL) {
+ perror("reset flg file open error");
+ return -1;
+ }
+ fclose(fp);
+#endif
+
+ // Factory Reset Run
+ reset_cmd[1] = reset_flag;
+ __system(reset_cmd);
+
+ // open log file (add local time)
+ fp = fopen(LOG_FILE, "a");
+ if (fp == NULL) {
+ perror("reset log file open error");
+ return -2;
+ }
+
+ // write finish log file
+ fprintf(fp, "End Factory Reset\n%d-%02d-%02d %02d:%02d:%02d\n",
+ tm2.tm_year + 1900, tm2.tm_mon + 1, tm2.tm_mday,
+ tm2.tm_hour, tm2.tm_min, tm2.tm_sec);
+ fclose(fp);
+
+ // remove reset flag file, sync and reboot
+#if 0
+ unlink(RESET_FLAG_FILE);
+#endif
+ sync();
+
+#ifdef DEBUG_BINARY
+ reboot(LINUX_REBOOT_CMD_RESTART);
+#else
+ const char *reboot_cmd[] = {"/usr/sbin/reboot", "debug0x4f4c", NULL};
+ __system(reboot_cmd);
+#endif
+
+ return 0;
+}