+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ *
+ *
+ * OSU is a tool to support Tizen OS Upgrade testing and development
+ *
+ */
+
#include <stdio.h>
+#include <stdbool.h>
+#include <getopt.h>
+#include <assert.h>
#include "update_control.h"
+#include "resize.h"
-int main(int argc, char **argv)
+
+struct arguments {
+ bool resize;
+ bool update;
+};
+
+static void print_help(char*);
+
+static int parse_args(int argc, char **argv, struct arguments *args)
{
- int ret = 0;
+ assert(argv);
+ assert(args);
+
+ args->resize = false;
+ args->update = true;
+
+ struct option long_options[] = {
+ {"resize", no_argument, NULL, 'r'},
+ {"update", no_argument, NULL, 'u'},
+ {"help", no_argument, NULL, 'h'},
+ {}
+ };
+
+ int opt;
+ while ((opt = getopt_long_only(argc, argv, "rh", long_options, NULL)) !=-1) {
+ args->update = false;
+
+ switch (opt) {
+ case 'r': {
+ args->resize = true;
+ return 0;
+ }
+ case 'u': {
+ args->update = true;
+ return 0;
+ }
+ case 'h': {
+ print_help(argv[0]);
+ return 0;
+ }
+ case '?': {
+ print_help(argv[0]);
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void print_help(char *my_name)
+{
+ assert(my_name);
+ printf("Usage:\n"
+ " %s [--resize|--update]\n\n"
+ "Possible arguments:\n"
+ " --help Print this help\n"
+ " --update Trigger the OS Upgrade\n"
+ " --resize Run resize2fs on the rootfs partition.\n"
+ " After that, performing the OS Upgrade will be impossible.\n\n"
+ "By default, without an argument, the OS Upgrade will be triggered.\n\n", my_name);
+}
+
+static int do_update()
+{
+ int ret = 0;
ret = update_control_initialize();
if (ret != UPDATE_CONTROL_ERROR_NONE) {
printf("Failed to initialize: %d\n", ret);
return ret;
}
+
+int main(int argc, char **argv)
+{
+ int ret = 0;
+ struct arguments args;
+
+ if (parse_args(argc, argv, &args) != 0) {
+ return 1;
+ }
+
+ if (args.resize) {
+ ret = do_resize();
+ } else if (args.update) {
+ ret = do_update();
+ }
+
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#define MAX_LINE_SIZE 1000
+
+static bool check_readonly(char *flags)
+{
+ assert(flags);
+ char *saveptr = NULL;
+ char *token = strtok_r(flags, ",", &saveptr);
+
+ while (token != NULL) {
+ if (strncmp(token, "ro", 3) == 0) {
+ return true;
+ }
+ token = strtok_r(NULL, ",", &saveptr);
+ }
+
+ return false;
+}
+
+static char *get_dev_name(const char *device_mount_point)
+{
+ FILE *file = fopen("/proc/mounts", "r");
+ if (file == NULL) {
+ fprintf(stderr,"/proc/mounts open error (%d): %m\n", errno);
+ return NULL;
+ }
+
+ char line[MAX_LINE_SIZE];
+ char *dev_name = NULL;
+
+ while ((fgets(line, MAX_LINE_SIZE, file)) != NULL) {
+ char *saveptr = NULL;
+
+ char *dev_name_candidate = strtok_r(line, " ", &saveptr);
+ char *mount_point = strtok_r(NULL, " ", &saveptr);
+ strtok_r(NULL, " ", &saveptr); // skip FS type
+ char *flags = strtok_r(NULL, " ", &saveptr);
+
+ if (dev_name_candidate == NULL || mount_point == NULL || flags == NULL) {
+ fprintf(stderr, "/proc/mounts parsing error\n");
+ goto out;
+ }
+
+ if (strncmp(mount_point, device_mount_point, strlen(device_mount_point)+1) == 0) {
+ if (check_readonly(flags)) {
+ fprintf(stderr, "The device %s is mounted as read-only. Please, remount"
+ " the filesystem as RW and try again:\n mount -o rw,remount %s\n",
+ dev_name_candidate, device_mount_point);
+ goto out;
+ }
+
+ dev_name = strdup(dev_name_candidate);
+ if (dev_name == NULL) {
+ fprintf(stderr,"Memory allocation error (%d): %m\n", errno);
+ goto out;
+ }
+
+ break;
+ }
+ }
+
+ if (dev_name == NULL) {
+ fprintf(stderr, "Not found rootfs in /proc/mounts\n");
+ }
+
+out:
+ fclose(file);
+ return dev_name;
+}
+
+static int run_resize(const char *dev_name)
+{
+ int ret = 0;
+ pid_t pid = fork();
+
+ if (pid == -1) {
+ fprintf(stderr, "fork() error: (%d) %m\n", errno);
+ return 1;
+ }
+
+ if (pid == 0) {
+ execl("/sbin/resize2fs", "resize2fs", dev_name, NULL);
+ } else {
+ int r, status;
+ bool is_ok;
+
+ do {
+ r = waitpid(pid, &status, 0);
+ is_ok = r >= 0;
+ } while (!is_ok && errno == EINTR);
+
+ if (!is_ok) {
+ fprintf(stderr, "resize2fs on %s execution error: (%d) %m\n", dev_name, errno);
+ return 1;
+ }
+
+ if (WIFEXITED(status))
+ ret = WEXITSTATUS(status);
+ else if (WIFSIGNALED(status))
+ ret = WTERMSIG(status);
+ else if (WIFSTOPPED(status))
+ ret = WSTOPSIG(status);
+ }
+ return ret;
+}
+
+static int resize_mount_point(const char *device_mount_point)
+{
+ int ret = 0;
+ printf("\nResizing %s\n", device_mount_point);
+ char *dev_name = get_dev_name(device_mount_point);
+ if (dev_name == NULL)
+ return 1;
+
+ ret = run_resize(dev_name);
+
+ free(dev_name);
+ return ret;
+}
+
+int do_resize()
+{
+ int ret = 0;
+ ret = resize_mount_point("/");
+ if (ret == 0) {
+ ret = resize_mount_point("/hal");
+ }
+ return ret;
+}