Add 'osu --resize' command to support resizing of the rootfs partition. 08/309608/1 accepted/tizen/8.0/unified/20240416.155535
authorMateusz Moscicki <m.moscicki2@partner.samsung.com>
Wed, 3 Apr 2024 09:40:53 +0000 (11:40 +0200)
committerChanwoo Choi <cw00.choi@samsung.com>
Fri, 12 Apr 2024 11:11:08 +0000 (20:11 +0900)
resize2fs is disabled in initrd to not modify the flashed image during
system boot, so that delta file can be applied during OS Upgrade.
However additional software may need to be installed during development,
so the ability to perfrom resize is added.
To resize, the rootfs partition must be mounted as RW:

    mount -o rw,remount /
    osu --resize

Change-Id: I74914464295629db5e8e2b696f41e1eb7a316b02

tools/osu/CMakeLists.txt
tools/osu/osu.c
tools/osu/resize.c [new file with mode: 0644]
tools/osu/resize.h [new file with mode: 0644]

index b9a836020d528d82367bee463633e16d36a05454..a1e662871ae6f8c960484f7f943e9b638cedc71d 100644 (file)
@@ -2,9 +2,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
 SET(OUTPUT_BIN_NAME osu)
 PROJECT(update-control-tools-${OUTPUT_BIN_NAME} C)
 
-INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
 
-FILE(GLOB_RECURSE SRCS osu.c)
+FILE(GLOB_RECURSE SRCS osu.c resize.c)
 ADD_EXECUTABLE(${OUTPUT_BIN_NAME} ${SRCS})
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
 TARGET_LINK_LIBRARIES(${OUTPUT_BIN_NAME} ${REQUIRED_PKGS_LDFLAGS} update-control)
index d4158db9b892f84e12935f52061307f468140316..744ba47d914cb506b2842c5c34efc90b94c8b356 100644 (file)
@@ -1,11 +1,98 @@
+/*
+ * 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);
@@ -41,3 +128,21 @@ cleanup:
 
        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;
+}
diff --git a/tools/osu/resize.c b/tools/osu/resize.c
new file mode 100644 (file)
index 0000000..3462b76
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * 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;
+}
diff --git a/tools/osu/resize.h b/tools/osu/resize.h
new file mode 100644 (file)
index 0000000..8c9894d
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+int do_resize();