Add database versioning and upgrading.
authorJan Cybulski <j.cybulski@samsung.com>
Fri, 8 Nov 2013 13:42:04 +0000 (14:42 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 21 Nov 2013 15:57:53 +0000 (16:57 +0100)
[Issue#]       SSDWSSP-615
[Bug/Feature]  Database upgrade was not possible without data loss.
[Cause]        N/A

[Solution]     Enable database upgrading by sequential calling upgrade
               sql scripts.
               Also, move all sql files to /usr/share/privilege-control/.

[Verification] -Remove one of the update files *-to-v2.sql in /db/updates,
               build and check if %check script properly detects lack of
               that file (build should stop with error).
               -Add that file again.
               -Build newest libprivilege-control (this)
                        and libprivilege-control-0.0.58
                        and libprivilege-control-0.0.59.
               -Install libprivilege-control-0.0.58, and then install newest.
               -Should install without problems. Run tests.
               -Remove database, install V59, and then install newest.
               -Should install without problems, Run tests.
               -Remove database, install newest.
               -Should install without problems, Run tests.

Change-Id: I5b232cba86c252d3ba2ac2e5432dcad816790823

CMakeLists.txt
db/rules-db-sql-udf.c
db/rules-db.sql
db/updater.sh [new file with mode: 0755]
db/updates/update-rules-db-data-to-v2.sql [new file with mode: 0644]
db/updates/update-rules-db-data-to-v3.sql [new file with mode: 0644]
db/updates/update-rules-db-to-v2.sql [new file with mode: 0644]
db/updates/update-rules-db-to-v3.sql [new file with mode: 0644]
packaging/libprivilege-control.spec
smack-rules.service

index b77c5cc..d271576 100644 (file)
@@ -96,9 +96,21 @@ INSTALL(FILES .privilege_control_app_gids.db DESTINATION /opt/dbspace)
 #INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/udev/ DESTINATION lib/udev)
 INSTALL(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/slp-su DESTINATION bin)
 
-INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/db/rules-db.sql DESTINATION /opt/dbspace)
-INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/db/rules-db-data.sql DESTINATION /opt/dbspace)
-INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/db/load-rules-db.sql DESTINATION /opt/etc/smack/)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/db/rules-db.sql DESTINATION /usr/share/privilege-control)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/db/rules-db-data.sql DESTINATION /usr/share/privilege-control)
+INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/db/updates/ DESTINATION /usr/share/privilege-control/updates)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/db/updater.sh DESTINATION /usr/share/privilege-control
+     PERMISSIONS OWNER_READ
+                 OWNER_WRITE
+                 OWNER_EXECUTE
+                 GROUP_READ
+                 GROUP_WRITE
+                 GROUP_EXECUTE
+                 WORLD_READ
+                 WORLD_WRITE
+                 WORLD_EXECUTE)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/db/load-rules-db.sql DESTINATION /usr/share/privilege-control)
+
 
 INSTALL(FILES ${PROJECT_SOURCE_DIR}/smack-rules.service
        DESTINATION /usr/lib/systemd/system
index bd079b0..9de1b7b 100644 (file)
 * @brief       This file contains implementation of a SQLite module used in rules-db.
 */
 
+/*
+ * WARNING FOR DEVELOPER:
+ * Changing this file has to keep backward compatibility.
+ * While you need to make a change that breaks backward compatibility,
+ * you have to build all older versions of librules-db-sql-udf.so library
+ * and pack them in libprivilege-control package, so that old update
+ * sql scripts could use older versions of this library.
+ * Alternatively if you need changes that are not backward compatible,
+ * you can make a separate library built from a separate .c file.
+ */
+
 #include <sqlite3ext.h>
 
 #define UNUSED __attribute__((unused))
@@ -166,4 +177,4 @@ int sqlite3_extension_init( sqlite3 *p_db,
                                bitwise_or_step, bitwise_or_final);
 
        return 0;
-}
\ No newline at end of file
+}
index a7fba4c..58ab1e2 100644 (file)
@@ -881,4 +881,4 @@ FROM    (
         )
 ORDER BY subject, object ASC;
 
-COMMIT TRANSACTION;
\ No newline at end of file
+COMMIT TRANSACTION;
diff --git a/db/updater.sh b/db/updater.sh
new file mode 100755 (executable)
index 0000000..2e11d1c
--- /dev/null
@@ -0,0 +1,90 @@
+#!/bin/sh
+
+#database updater requires making proper sql scripts
+
+if [ $# -eq 2 -a "$1" = "--check-files" ]
+then
+    echo "Checking sql update files"
+    check="1"
+    dir="$2"
+    sqlitecmd="true"
+elif [ $# -eq 0 ]
+then
+    echo "Applying sql update files on db"
+    check="0"
+    dir=""
+    sqlitecmd="sqlite3"
+else
+    exit 1
+fi
+
+
+database="$dir/opt/dbspace/.rules-db.db3"
+scripts_dir="$dir/usr/share/privilege-control"
+updates_dir="$dir/usr/share/privilege-control/updates"
+
+echo $database
+
+
+if [ $check -eq 0 -a ! -e "$database" ]
+then
+    echo "Creating database from scratch"
+    $sqlitecmd "$database" < "$scripts_dir/rules-db.sql"
+    $sqlitecmd "$database" < "$scripts_dir/rules-db-data.sql"
+else
+    db_version="`$sqlitecmd $database "PRAGMA user_version;"`"
+    # Parsing DB version from rules-db.sql
+    db_version_to_install="`grep $scripts_dir/rules-db.sql -e '^[[:space:]]*PRAGMA user_version'`"
+    db_version_to_install="`echo \"$db_version_to_install\" | sed -r 's/.*([0-9]+).*/\1/'`"
+
+    if [ -z "$db_version_to_install" ]
+    then echo "Version to be installed: unknown: '$db_version_to_install'"
+         exit 1
+    fi
+
+    if [ 0"$db_version" -eq 0 ]
+    then echo "user_version PRAGMA is not set on database. Assuming version 1 or 2"
+         #minor hack for backward compatibility,
+         #workaround for older databases that were not versioned properly.
+         db_version="`$sqlitecmd $database \"PRAGMA table_info(app_path)\"`"
+         db_version="`echo \"$db_version\" | grep -e \"access_reverse\"`"
+         if [ -z "$db_version" ]
+         then db_version=1
+         else db_version=2
+         fi
+    fi
+
+    echo "Current database version is $db_version"
+    echo "Version being installed now is $db_version_to_install"
+
+    if [ "$db_version" -gt "$db_version_to_install" ]
+    then echo "Downgrade database version not possible without data loss,"
+         echo "Remove current database manually (rm $database) and retry."
+         exit 1
+    fi
+    for i in `seq $((db_version+1)) $db_version_to_install`
+    do
+        echo "Database upgrade to version $i:"
+        update_script="$updates_dir/update-rules-db-to-v$i.sql"
+        update_data_script="$updates_dir/update-rules-db-data-to-v$i.sql"
+        if [ ! -e  "$update_script" ]
+        then
+            echo "No $update_script available, make one"
+            exit 1
+        fi
+        if [ ! -e  "$update_data_script" ]
+        then
+            echo "No $update_data_script available, make one"
+            exit 1
+        fi
+        echo "Loading $update_script"
+        $sqlitecmd "$database" < "$update_script"
+        echo "Loading $update_data_script"
+        $sqlitecmd "$database" < "$update_data_script"
+    done
+    #after updating schema, make veiws etc.
+    $sqlitecmd "$database" < "$scripts_dir/rules-db.sql"
+    $sqlitecmd "$database" < "$scripts_dir/rules-db-data.sql"
+
+fi
+
diff --git a/db/updates/update-rules-db-data-to-v2.sql b/db/updates/update-rules-db-data-to-v2.sql
new file mode 100644 (file)
index 0000000..802bbd6
--- /dev/null
@@ -0,0 +1,5 @@
+BEGIN EXCLUSIVE TRANSACTION;
+
+INSERT OR IGNORE INTO app_path_type(name) VALUES("NPRUNTIME_PATH");
+
+COMMIT TRANSACTION;
diff --git a/db/updates/update-rules-db-data-to-v3.sql b/db/updates/update-rules-db-data-to-v3.sql
new file mode 100644 (file)
index 0000000..e80386a
--- /dev/null
@@ -0,0 +1,7 @@
+BEGIN EXCLUSIVE TRANSACTION;
+
+--assume, that database is in version V2
+--place your queries for updating data to V3 here
+
+
+COMMIT TRANSACTION;
diff --git a/db/updates/update-rules-db-to-v2.sql b/db/updates/update-rules-db-to-v2.sql
new file mode 100644 (file)
index 0000000..baa9841
--- /dev/null
@@ -0,0 +1,7 @@
+BEGIN EXCLUSIVE TRANSACTION;
+
+ALTER TABLE app_path ADD COLUMN access_reverse INTEGER NOT NULL DEFAULT 0;
+
+PRAGMA user_version = 2;
+
+COMMIT TRANSACTION;
diff --git a/db/updates/update-rules-db-to-v3.sql b/db/updates/update-rules-db-to-v3.sql
new file mode 100644 (file)
index 0000000..b8a41b1
--- /dev/null
@@ -0,0 +1,11 @@
+--smaple file for future work
+BEGIN EXCLUSIVE TRANSACTION;
+
+--assume, that database is in version V2
+--place your queries to update the database schema to V3 here
+
+
+
+PRAGMA user_version = 3;
+
+COMMIT TRANSACTION;
index 22705d4..471f29c 100644 (file)
@@ -100,15 +100,14 @@ then
        mkdir -p /opt/etc/smack-app-early/accesses.d
 fi
 
-sqlite3 /opt/dbspace/.rules-db.db3 < /opt/dbspace/rules-db.sql
-rm -f /opt/dbspace/rules-db.sql
-
-sqlite3 /opt/dbspace/.rules-db.db3 < /opt/dbspace/rules-db-data.sql
-rm -f /opt/dbspace/rules-db-data.sql
+/usr/share/privilege-control/updater.sh
 
 api_feature_loader --verbose --dir=/usr/share/privilege-control/
 api_feature_loader --verbose --rules=/usr/share/privilege-control/ADDITIONAL_RULES.smack
 
+%check
+./db/updater.sh --check-files %{buildroot}
+
 %files
 %{_libdir}/*.so.*
 %{_libdir}/librules-db-sql-udf.so
@@ -121,9 +120,11 @@ api_feature_loader --verbose --rules=/usr/share/privilege-control/ADDITIONAL_RUL
 /usr/bin/api_feature_loader
 #link to activate systemd service
 /usr/lib/systemd/system/multi-user.target.wants/smack-rules.service
-/opt/dbspace/rules-db.sql
-/opt/dbspace/rules-db-data.sql
-/opt/etc/smack/load-rules-db.sql
+/usr/share/privilege-control/rules-db.sql
+/usr/share/privilege-control/rules-db-data.sql
+/usr/share/privilege-control/updater.sh
+/usr/share/privilege-control/updates/*
+/usr/share/privilege-control/load-rules-db.sql
 
 %files conf
 /etc/group
index f8bbc2b..c4130fe 100644 (file)
@@ -4,7 +4,7 @@ Before=starter.service
 
 [Service]
 Type=oneshot
-ExecStartPre =  /bin/bash -c '/usr/bin/sqlite3 /opt/dbspace/.rules-db.db3 < /opt/etc/smack/load-rules-db.sql'
+ExecStartPre =  /bin/bash -c '/usr/bin/sqlite3 /opt/dbspace/.rules-db.db3 < /usr/share/privilege-control/smack/load-rules-db.sql'
 ExecStart = /bin/bash -c '/bin/grep ^ /opt/etc/smack/boot-rules.smack --line-buffered > /smack/change-rule'
 
 [Install]