tizen 2.3 release tizen_2.3 submit/tizen_2.3/20150202.052747 tizen_2.3_release
authorjk7744.park <jk7744.park@samsung.com>
Sun, 1 Feb 2015 03:58:58 +0000 (12:58 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Sun, 1 Feb 2015 03:58:58 +0000 (12:58 +0900)
40 files changed:
.gitattributes [new file with mode: 0644]
.gitignore [new file with mode: 0644]
Makefile.am
README [deleted file]
TODO [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
conf/systemd/ignore-units
configure.ac
packaging/system-plugin-common.spec
rules/51-tizen-udev-default.rules [new file with mode: 0644]
scripts/change-booting-mode.sh
scripts/cleanup-storage.sh [new file with mode: 0644]
scripts/tizen-boot.sh.in
scripts/tizen-fstrim-on-charge.sh
src/ghost/ghost.c [new file with mode: 0644]
src/ghost/ghost.conf.m4 [new file with mode: 0644]
src/shared/conf-parser.c [new file with mode: 0644]
src/shared/conf-parser.h [new file with mode: 0644]
src/shared/dbus-common.h [new file with mode: 0644]
src/shared/fileio.c [new file with mode: 0644]
src/shared/fileio.h [new file with mode: 0644]
src/shared/macro.h [new file with mode: 0644]
src/shared/systemd.c [new file with mode: 0644]
src/shared/systemd.h [new file with mode: 0644]
src/shared/util.c [new file with mode: 0644]
src/shared/util.h [new file with mode: 0644]
sysctl.d/50-tizen-default.conf.in [new file with mode: 0644]
units/cleanup-storage.service [new file with mode: 0644]
units/cleanup-storage.timer [new file with mode: 0644]
units/ghost.service [new file with mode: 0644]
units/init-conf.service [new file with mode: 0644]
units/tizen-boot.target [new file with mode: 0644]
units/tizen-fstrim-user.service
units/tizen-journal-flush.service [new file with mode: 0644]
units/tizen-readahead-collect-stop.service
units/tizen-readahead-collect.service.in
units/tizen-readahead-replay.service.in
units/tizen-runtime.target [new file with mode: 0644]
units/tizen-system.target [new file with mode: 0644]
units/wm_ready.service

diff --git a/.gitattributes b/.gitattributes
new file mode 100644 (file)
index 0000000..1841508
--- /dev/null
@@ -0,0 +1 @@
+*.[ch] whitespace=tab-in-indent,trailing-space
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..7385704
--- /dev/null
@@ -0,0 +1,25 @@
+*.a
+*.cache
+*.html
+*.la
+*.lo
+*.log
+*.o
+*.plist
+*.pyc
+*.stamp
+*.swp
+*.trs
+*~
+.deps/
+.dirstamp
+.libs/
+Makefile.in
+aclocal.m4
+config.h
+config.h.in
+config.log
+config.status
+configure
+/Makefile
+/TAGS
index a5376cd..cb7c5bc 100644 (file)
@@ -15,6 +15,9 @@ userunitdir=$(prefix)/lib/systemd/user
 udevlibexecdir=$(rootprefix)/lib/udev
 udevhomedir=$(udevlibexecdir)
 udevrulesdir=$(udevlibexecdir)/rules.d
+if MOBILE
+sysctldir=$(prefix)/lib/sysctl.d
+endif
 
 # And these are the special ones for /
 rootprefix=@rootprefix@
@@ -25,6 +28,12 @@ if WITH_ENGMODE
 engbindir=/opt/usr/devel/$(rootbindir)
 endif
 
+if MOBILE
+noinst_LTLIBRARIES =
+noinst_DATA =
+sysctl_DATA =
+endif
+
 bin_SCRIPTS =
 rc_SCRIPTS =
 SCRIPT_IN_FILES =
@@ -39,6 +48,17 @@ if WITH_ENGMODE
 engbin_PROGRAMS =
 endif
 
+if MOBILE
+AM_CPPFLAGS = \
+       -include $(top_builddir)/config.h \
+       -I $(top_srcdir)/src \
+       -I $(top_srcdir)/src/shared \
+       $(OUR_CPPFLAGS)
+
+AM_CFLAGS = $(OUR_CFLAGS)
+AM_LDFLAGS = $(OUR_LDFLAGS)
+endif
+
 INSTALL_EXEC_HOOKS =
 UNINSTALL_EXEC_HOOKS =
 
@@ -56,6 +76,10 @@ MULTI_USER_TARGET_WANTS =
 DEFAULT_TARGET_WANTS =
 SYSCONF_LOCAL_FS_TARGET_WANTS =
 
+if MOBILE
+GRAPHICAL_TARGET_WANTS =
+endif
+
 install-target-wants-hook:
        where=$(systemunitdir) && what="$(SHUTDOWN_TARGET_WANTS)" && wants=shutdown.target && $(add-wants)
        where=$(systemunitdir) && what="$(LOCAL_FS_TARGET_WANTS)" && wants=local-fs.target && $(add-wants)
@@ -70,6 +94,9 @@ install-target-wants-hook:
        where=$(systemunitdir) && what="$(TIZEN_SYSTEM_TARGET_WANTS)" && wants=tizen-system.target && $(add-wants)
        where=$(systemunitdir) && what="$(TIZEN_RUNTIME_TARGET_WANTS)" && wants=tizen-runtime.target && $(add-wants)
        where=$(systemunitdir) && what="$(TIZEN_RUNTIME_TARGET_WANTS)" && wants=tizen-runtime.target && $(add-wants)
+if MOBILE
+       where=$(systemunitdir) && what="$(GRAPHICAL_TARGET_WANTS)" && wants=graphical.target && $(add-wants)
+endif
        where=$(systemunitdir) && what="$(DEFAULT_TARGET_WANTS)" && wants=default.target && $(add-wants)
        where=$(systemconfigunitdir) && what="$(SYSCONF_LOCAL_FS_TARGET_WANTS)" && wants=local-fs.target && $(add-wants)
 
@@ -103,9 +130,65 @@ INSTALL_EXEC_HOOKS += \
 #  AM_V_LN_0 = @echo "  LN      " $@;
 
 # ------------------------------------------------------------------------------
+if MOBILE
+bin_SCRIPTS += \
+       scripts/change-booting-mode.sh \
+       scripts/cleanup-storage.sh \
+       scripts/tizen-fstrim-on-charge.sh
+
+systemunit_DATA += \
+       units/check-mount.service \
+       units/cleanup-storage.service \
+       units/cleanup-storage.timer \
+       units/ghost.service \
+       units/init-conf.service \
+       units/tizen-boot.target \
+       units/tizen-fstrim-user.service \
+       units/tizen-fstrim-user.timer \
+       units/tizen-generate-env.service \
+       units/tizen-init.target \
+       units/tizen-init-check.service \
+       units/tizen-init-done.service \
+       units/tizen-initial-boot-done.service \
+       units/tizen-journal-flush.service \
+       units/tizen-readahead-collect.service \
+       units/tizen-readahead-collect-stop.service \
+       units/tizen-readahead-replay.service \
+       units/tizen-runtime.target \
+       units/tizen-system.target
+
+SYSINIT_TARGET_WANTS += \
+       init-conf.service
+
+TIMERS_TARGET_WANTS += \
+       cleanup-storage.timer
+
+BASIC_TARGET_WANTS += \
+       cleanup-storage.service \
+       tizen-generate-env.service \
+       tizen-init-check.service
+
+TIZEN_INIT_TARGET_WANTS += \
+       tizen-init-done.service \
+       tizen-readahead-collect.service
+
+MULTI_USER_TARGET_WANTS += \
+       ghost.service \
+       tizen-boot.target \
+       tizen-runtime.target \
+       tizen-system.target
+
+GRAPHICAL_TARGET_WANTS += \
+       tizen-fstrim-user.timer \
+       tizen-initial-boot-done.service \
+       tizen-journal-flush.service \
+       tizen-readahead-replay.service
+
+udevrules_DATA += \
+       rules/51-tizen-udev-default.rules
+else
 bin_SCRIPTS += \
        scripts/change-booting-mode.sh \
-       scripts/tizen-boot.sh \
        scripts/tizen-fstrim-on-charge.sh
 
 systemunit_DATA += \
@@ -121,9 +204,6 @@ systemunit_DATA += \
        units/tizen-initial-boot-done.service \
        units/tizen-init-done.service
 
-systemdignoreunit_DATA += \
-       conf/systemd/ignore-units
-
 BASIC_TARGET_WANTS += \
        tizen-generate-env.service \
        tizen-init-check.service
@@ -132,9 +212,6 @@ TIZEN_INIT_TARGET_WANTS += \
        tizen-readahead-collect.service \
        tizen-init-done.service
 
-TIZEN_SYSTEM_TARGET_WANTS += \
-       check-mount.service
-
 MULTI_USER_TARGET_WANTS += \
        tizen-readahead-replay.service
 
@@ -142,14 +219,34 @@ DEFAULT_TARGET_WANTS += \
        tizen-fstrim-user.timer \
        tizen-initial-boot-done.service
 
+udevrules_DATA += \
+       rules/51-tizen-udev-default.rules
+endif
+
+systemdignoreunit_DATA += \
+       conf/systemd/ignore-units
+
+TIZEN_SYSTEM_TARGET_WANTS += \
+       check-mount.service
+
 if WITH_UDEVD_KILLER
 systemunit_DATA += \
        units/systemd-udevd-kill.service \
        units/systemd-udevd-kill.timer
 
+if MOBILE
+GRAPHICAL_TARGET_WANTS += \
+       systemd-udevd-kill.timer
+else
 DEFAULT_TARGET_WANTS += \
        systemd-udevd-kill.timer
 endif
+endif
+
+if MOBILE
+sysctl_DATA += \
+       sysctl.d/50-tizen-default.conf
+endif
 
 if WITH_WMREADY
 systemunit_DATA += \
@@ -159,6 +256,54 @@ TIZEN_BOOT_TARGET_WANTS += \
        wm_ready.service
 endif
 
+if MOBILE
+sysconf_DATA += \
+       src/ghost/ghost.conf
+
+ghost_SOURCES = \
+       src/ghost/ghost.c
+
+ghost_CFLAGS = \
+       $(AM_CFLAGS) \
+       $(DBUS_CFLAGS) \
+       $(GLIB_CFLAGS) \
+       $(GIO_CFLAGS)
+
+bin_PROGRAMS = \
+       ghost
+
+ghost_LDADD = \
+       libsystem-plugin-shared.la \
+       $(DBUS_LIBS) \
+       $(GLIB_LIBS) \
+       $(GIO_LIBS)
+
+# ------------------------------------------------------------------------------
+noinst_LTLIBRARIES += \
+       libsystem-plugin-shared.la
+
+libsystem_plugin_shared_la_SOURCES = \
+       src/shared/conf-parser.c \
+       src/shared/conf-parser.h \
+       src/shared/dbus-common.h \
+       src/shared/fileio.c \
+       src/shared/fileio.h \
+       src/shared/macro.h \
+       src/shared/systemd.c \
+       src/shared/systemd.h \
+       src/shared/util.c \
+       src/shared/util.h
+
+libsystem_plugin_shared_la_CFLAGS = \
+       $(AM_CFLAGS) \
+        $(DBUS_CFLAGS) \
+       $(GLIB_CFLAGS) \
+       $(GIO_CFLAGS)
+
+libsystem_plugin_shared_la_LIBADD = \
+       $(DBUS_LIBS)
+endif
+
 # ------------------------------------------------------------------------------
 substitutions = \
        '|rootlibexecdir=$(rootlibexecdir)|' \
@@ -205,7 +350,8 @@ substitutions = \
        '|PYTHON_BINARY=$(PYTHON_BINARY)|' \
        '|INITAILBOOT_DONE=$(INITAILBOOT_DONE)|' \
        '|INITIALIZE_DONE=$(INITIALIZE_DONE)|' \
-       '|READAHEAD_DIR=$(READAHEAD_DIR)|'
+       '|READAHEAD_DIR=$(READAHEAD_DIR)|' \
+       '|DIRTY_WRITEBACK_CENTISECS=$(DIRTY_WRITEBACK_CENTISECS)|'
 
 SED_PROCESS = \
        $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
@@ -222,6 +368,15 @@ units/%: units/%.in Makefile
        $(SED_PROCESS)
        $(AM_V_GEN)chmod +x $@
 
+if MOBILE
+src/%: src/%.m4
+       $(AM_V_at)$(MKDIR_P) $(dir $@)
+       $(AM_V_M4)$(M4) -P $(M4_DEFINES) < $< > $@
+
+sysctl.d/%: sysctl.d/%.in Makefile
+       $(SED_PROCESS)
+endif
+
 units/%: units/%.m4 Makefile
        $(AM_V_M4)$(MKDIR_P) $(dir $@)
        $(AM_V_M4)$(M4) -P $(M4_DEFINES) -DFOR_SYSTEM=1 < $< > $@
diff --git a/README b/README
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..c75dfbb
--- /dev/null
+++ b/TODO
@@ -0,0 +1,16 @@
+log:
+
+* There is no regular log api in this package. We need some of regular
+  log api or wrapper.
+
+ghost:
+
+* boottime check point is hard coded now. That should be configurable.
+
+* bootloader time is not ready yet. After that ghost have to generate
+  time that and sum of that and platform boot time.
+
+* ghost dir disk usage threshold should be configurable.
+
+* bootchart generate directory should be parsed by bootchart.conf. Now
+  it is hard coded to "/run/log".
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..968bc8e
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+set -e
+
+if [ -f .git/hooks/pre-commit.sample ] && [ ! -f .git/hooks/pre-commit ]; then
+    # This part is allowed to fail
+    cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \
+        chmod +x .git/hooks/pre-commit && \
+        echo "Activated pre-commit hook." || :
+fi
+
+# README and INSTALL are required by automake, but may be deleted by
+# clean up rules. to get automake to work, simply touch these here,
+# they will be regenerated from their corresponding *.in files by
+# ./configure anyway.
+touch README INSTALL
+
+# Make sure m4 directory exist
+mkdir -p m4
+
+autoreconf --force --install --verbose || exit $?
index df8bd62..95062a1 100644 (file)
@@ -16,7 +16,6 @@ ode-server.service
 opt-usr-fsck.service
 osp-tmpdir-setup.service
 pkgmgr_recovery.service
-power_qcom_init.service
 pulseaudio.service
 qmuxd.service
 qseecom_ready.service
@@ -34,7 +33,6 @@ system-server.service
 tee-qsee.service
 telephony-daemon.service
 time.service
-trm.service
 wifi-module-check.service
 wm_ready.service
 wrt-security-daemon.service
index 499dcc2..cf97dd4 100644 (file)
@@ -5,11 +5,16 @@ AC_PREREQ([2.68])
 AC_INIT(system-plugin-common, 0.0.01, [BUG-REPORT-ADDRESS])
 
 AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_HEADERS([config.h])
+
 AC_USE_SYSTEM_EXTENSIONS
 AC_SYS_LARGEFILE
 AC_PREFIX_DEFAULT([/usr])
 AM_INIT_AUTOMAKE([foreign])
 
+LT_PREREQ(2.2)
+LT_INIT([disable-static])
+
 # Checks for programs.
 AC_PROG_MKDIR_P
 AC_PROG_LN_S
@@ -17,70 +22,13 @@ AC_PROG_SED
 AC_PROG_GREP
 AC_PROG_AWK
 #AC_PROG_INSTALL
-AC_PATH_PROG([M4], [m4])
-
-# ------------------------------------------------------------------------------
-AC_ARG_ENABLE([xattr],
-        AS_HELP_STRING([--disable-xattr],[Disable optional XATTR support]),
-                [case "${enableval}" in
-                        yes) have_xattr=yes ;;
-                        no) have_xattr=no ;;
-                        *) AC_MSG_ERROR(bad value ${enableval} for --disable-xattr) ;;
-                esac],
-                [have_xattr=auto])
-
-if test "x${have_xattr}" != xno ; then
-        AC_CHECK_HEADERS(
-                [attr/xattr.h],
-                [have_xattr=yes],
-                [if test "x$have_xattr" = xyes ; then
-                        AC_MSG_ERROR([*** XATTR headers not found.])
-                fi])
-
-        AC_CHECK_LIB(
-                [attr],
-                [fsetxattr],
-                [have_xattr=yes],
-                [if test "x$have_xattr" = xyes ; then
-                        AC_MSG_ERROR([*** libattr not found.])
-                fi])
-
-        if test "x$have_xattr" = xyes ; then
-                XATTR_LIBS="-lattr"
-                AC_DEFINE(HAVE_XATTR, 1, [XATTR available])
-        else
-                have_xattr=no
-        fi
-else
-        XATTR_LIBS=
-fi
-AC_SUBST(XATTR_LIBS)
-AM_CONDITIONAL([HAVE_XATTR], [test "x$have_xattr" != xno])
 
-# ------------------------------------------------------------------------------
-AC_ARG_ENABLE([smack], AS_HELP_STRING([--disable-smack],[Disable optional SMACK support]),
-                [case "${enableval}" in
-                        yes) have_smack=yes ;;
-                        no) have_smack=no ;;
-                        *) AC_MSG_ERROR(bad value ${enableval} for --disable-smack) ;;
-                esac],
-                [have_smack=auto])
-
-if test "x${have_xattr}" = xno; then
-        if test "x${have_smack}" = xyes; then
-                AC_MSG_ERROR(SMACK requires xattr support)
-        else
-                have_smack=no
-        fi
-else
-        if test "x${have_smack}" = xauto; then
-                have_smack=yes
-        fi
-fi
-
-if test "x${have_smack}" = xyes ; then
-        AC_DEFINE(HAVE_SMACK, 1, [Define if SMACK is available])
-fi
+AC_PROG_CC
+AC_PROG_CC_C99
+AM_PROG_CC_C_O
+AC_PROG_GCC_TRADITIONAL
+AC_PATH_PROG([M4], [m4])
+M4_DEFINES=
 
 # ------------------------------------------------------------------------------
 AC_ARG_WITH([rootprefix],
@@ -90,26 +38,17 @@ AC_ARG_WITH([rootprefix],
 AC_SUBST([rootprefix], [$with_rootprefix])
 
 # ------------------------------------------------------------------------------
-AC_ARG_ENABLE([wmready],
-        AS_HELP_STRING([--disable-wmready], [without window manager waiting]),
-                [case "${enableval}" in
-                        yes) have_winmgr=yes ;;
-                        no) have_winmgr=no ;;
-                        *) AC_MSG_ERROR(bad value ${enableval} for --disable-wmready) ;;
-                esac],
-                have_winmgr=yes)
-AC_SUBST(WITH_WMREADY)
-AM_CONDITIONAL([WITH_WMREADY], [test "x$have_winmgr" != xno])
-
-# ------------------------------------------------------------------------------
 AC_ARG_ENABLE([engmode],
-        AS_HELP_STRING([--disable-engmode], [disable engineer mode]),
+        AS_HELP_STRING([--enable-engmode], [disable engineer mode]),
                 [case "${enableval}" in
                         yes) with_engmode=yes ;;
                         no) with_engmode=no ;;
                         *) AC_MSG_ERROR(bad value ${enableval} for --disable-engmode) ;;
                 esac],
-                with_engmode=no)
+                with_engmode=yes)
+if test "x$with_engmode" != "xno"; then
+        M4_DEFINES="$M4_DEFINES -DWITH_ENGMODE"
+fi
 AC_SUBST(WITH_ENGMODE)
 AM_CONDITIONAL([WITH_ENGMODE], [test "x$with_engmode" != xno])
 
@@ -137,6 +76,21 @@ AC_ARG_WITH(tizen-readahead,
 AC_SUBST(READAHEAD_DIR)
 
 # ------------------------------------------------------------------------------
+AC_ARG_ENABLE([engmode2],
+        AS_HELP_STRING([--enable-engmode2], [disable engineer mode2]),
+                [case "${enableval}" in
+                        yes) with_engmode2=yes ;;
+                        no) with_engmode2=no ;;
+                        *) AC_MSG_ERROR(bad value ${enableval} for --disable-engmode2) ;;
+                esac],
+                with_engmode2=yes)
+if test "x$with_engmode2" != "xno"; then
+        M4_DEFINES="$M4_DEFINES -DWITH_ENGMODE2"
+fi
+AC_SUBST(WITH_ENGMODE2)
+AM_CONDITIONAL([WITH_ENGMODE2], [test "x$with_engmode2" != xno])
+
+# ------------------------------------------------------------------------------
 AC_ARG_ENABLE([udevd-killer],
         AS_HELP_STRING([--enable-udevd-killer],
                        [install udevd killer service]),
@@ -150,7 +104,31 @@ AC_SUBST(WITH_UDEVD_KILLER)
 AM_CONDITIONAL([WITH_UDEVD_KILLER], [test "x$enable_udevd_killer" != xno])
 
 # ------------------------------------------------------------------------------
-M4_DEFINES=
+AC_ARG_ENABLE([mobile],
+        AS_HELP_STRING([--enable-mobile],
+                       [enable mobile configuration]),
+                [case "${enableval}" in
+                        yes) enable_mobile=yes ;;
+                        no) enable_mobile=no ;;
+                        *) AC_MSG_ERROR(bad value ${enableval} for --enable-mobile) ;;
+                esac],
+                enable_mobile=no)
+AC_SUBST(MOBILE)
+AM_CONDITIONAL([MOBILE], [test "x$enable_mobile" != xno])
+
+# ------------------------------------------------------------------------------
+AC_ARG_ENABLE([wmready],
+        AS_HELP_STRING([--disable-wmready], [without window manager waiting]),
+                [case "${enableval}" in
+                        yes) have_winmgr=yes ;;
+                        no) have_winmgr=no ;;
+                        *) AC_MSG_ERROR(bad value ${enableval} for --disable-wmready) ;;
+                esac],
+                have_winmgr=yes)
+AC_SUBST(WITH_WMREADY)
+AM_CONDITIONAL([WITH_WMREADY], [test "x$have_winmgr" != xno])
+
+# ------------------------------------------------------------------------------
 AC_ARG_ENABLE([frequent-fstrim],
         AS_HELP_STRING([--enable-frequent-fstrim],
                        [use more frequently fstrim timer]),
@@ -163,26 +141,33 @@ AC_ARG_ENABLE([frequent-fstrim],
 if test "x$enable_frequent_fstrim" == "xyes"; then
         M4_DEFINES="$M4_DEFINES -DWITH_FREQUENT_FSTRIM"
 fi
+
 AC_SUBST(M4_DEFINES)
 AC_SUBST(WITH_FREQUENT_FSTRIM)
 AM_CONDITIONAL([WITH_FREQUENT_FSTRIM], [test "x$enable_frequent_fstrim" != xno])
 
 # ------------------------------------------------------------------------------
+AC_ARG_WITH(dirty-writeback-centisecs,
+            AS_HELP_STRING([--with-dirty-writeback-centisecs=NUMBER],
+                           [Path to /etc/rc.local]),
+                           [DIRTY_WRITEBACK_CENTISECS="$withval"],
+                           [DIRTY_WRITEBACK_CENTISECS="500"])
+
+AC_DEFINE_UNQUOTED(DIRTY_WRITEBACK_CENTISECS, ["$DIRTY_WRITEBACK_CENTISECS"], [Path of /etc/rc.local script])
+AC_SUBST(DIRTY_WRITEBACK_CENTISECS)
+
+# ------------------------------------------------------------------------------
+PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.3.2])
+PKG_CHECK_MODULES(GLIB, [glib-2.0])
+PKG_CHECK_MODULES(GIO, [gio-2.0])
+
+# ------------------------------------------------------------------------------
 AC_CONFIG_FILES([Makefile])
 
 AC_OUTPUT
 AC_MSG_RESULT([
         $PACKAGE_NAME $VERSION
 
-        engineer mode:           ${with_engmode}
-
-        XATTR:                   ${have_xattr}
-        SMACK:                   ${have_smack}
-
-        window manager:          ${have_winmgr}
-        udevd killer:            ${enable_udevd_killer}
-        frequent fstrim:         ${enable_frequent_fstrim}
-
         prefix:                  ${prefix}
         rootprefix:              ${with_rootprefix}
         sysconf dir:             ${sysconfdir}
@@ -191,4 +176,13 @@ AC_MSG_RESULT([
         rootlib dir:             ${with_rootlibdir}
         initial boot done flag:  ${INITAILBOOT_DONE}
         inialized done flag:     ${INITIALIZE_DONE}
+
+        XATTR:                   ${have_xattr}
+        SMACK:                   ${have_smack}
+
+        engineer mode:           ${with_engmode}
+        window manager:          ${have_winmgr}
+        udevd killer:            ${enable_udevd_killer}
+        frequent fstrim:         ${enable_frequent_fstrim}
+        enable mobile:           ${enable_mobile}
 ])
index b94b675..b31b309 100644 (file)
@@ -1,8 +1,7 @@
 ###########################
 # Default feature config. #
 ###########################
-# SMACK
-%define WITH_SMACK 1
+
 # udev daemon killer unit
 %define WITH_UDEVD_KILLER 0
 # If window manager exist then waiting unit will be installed.
 
 %define WITH_FREQUENT_FSTRIM 0
 
-%if "%{_repository}" == "wearable"
+%if "%{?tizen_profile_name}" == "wearable"
 %define WITH_FREQUENT_FSTRIM 1
+%define dirty_writeback_centisecs 1000
 %endif
 
-%define _prefix_devel /opt/usr/devel
-
 Name: system-plugin-common
 Summary: system common file of system
 Version: 0.0.01
@@ -28,10 +26,11 @@ Source1001: %{name}.manifest
 
 BuildRequires: autoconf
 BuildRequires: automake
-%if %{WITH_SMACK}
-BuildRequires: libacl-devel
-BuildRequires: smack-devel
-%endif
+BuildRequires: libtool
+BuildRequires: kernel-headers
+BuildRequires: pkgconfig(dbus-1)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(gio-2.0)
 
 Requires: e2fsprogs
 Requires: /bin/grep
@@ -48,17 +47,9 @@ Startup files
 %build
 cp %{SOURCE1001} .
 
-aclocal
-automake --add-missing
-autoconf
-%configure \
+./autogen.sh
+%configure CFLAGS='-g -O0 -Werror' \
         --prefix=%{_prefix} \
-%if 0%{?tizen_build_binary_release_type_eng:1}
-        --enable-engmode \
-%endif
-%if %{WITH_SMACK}
-        --enable-smack \
-%endif
 %if ! %{WITH_WMREADY}
         --disable-wmready \
 %endif
@@ -68,6 +59,12 @@ autoconf
 %if %{WITH_FREQUENT_FSTRIM}
         --enable-frequent-fstrim \
 %endif
+%if ("%{?dirty_writeback_centisecs}" != "")
+        --with-dirty-writeback-centisecs=%{dirty_writeback_centisecs} \
+%endif
+%if "%{?tizen_profile_name}" == "mobile"
+        --enable-mobile
+%endif
 
 make %{?_smp_mflags}
 
@@ -77,6 +74,12 @@ make %{?_smp_mflags}
 mkdir -p $RPM_BUILD_ROOT%{_datadir}/license
 cat LICENSE > $RPM_BUILD_ROOT%{_datadir}/license/%{name}
 
+%if "%{?tizen_profile_name}" == "mobile"
+mkdir -p %{buildroot}%{_libdir}/sysctl.d
+mkdir -p %{buildroot}%{_sysconfdir}
+touch %{buildroot}%{_sysconfdir}/machine-id
+%endif
+
 %post
 touch %{_sysconfdir}/ld.so.nohwcap
 
@@ -85,7 +88,6 @@ touch %{_sysconfdir}/ld.so.nohwcap
 %{_datadir}/license/%{name}
 %{_sysconfdir}/systemd/default-extra-dependencies/ignore-units
 %{_bindir}/change-booting-mode.sh
-%{_bindir}/tizen-boot.sh
 
 # systemd service units
 %{_libdir}/systemd/system/tizen-generate-env.service
@@ -104,11 +106,9 @@ touch %{_sysconfdir}/ld.so.nohwcap
 %{_libdir}/systemd/system/tizen-init-done.service
 %{_libdir}/systemd/system/tizen-init.target.wants/tizen-init-done.service
 %{_libdir}/systemd/system/tizen-initial-boot-done.service
-%{_libdir}/systemd/system/default.target.wants/tizen-initial-boot-done.service
 
 # fstrim units
 %{_bindir}/tizen-fstrim-on-charge.sh
-%{_libdir}/systemd/system/default.target.wants/tizen-fstrim-user.timer
 %{_libdir}/systemd/system/tizen-fstrim-user.service
 %{_libdir}/systemd/system/tizen-fstrim-user.timer
 
@@ -117,12 +117,63 @@ touch %{_sysconfdir}/ld.so.nohwcap
 %{_libdir}/systemd/system/tizen-readahead-collect-stop.service
 %{_libdir}/systemd/system/tizen-init.target.wants/tizen-readahead-collect.service
 %{_libdir}/systemd/system/tizen-readahead-replay.service
-%{_libdir}/systemd/system/multi-user.target.wants/tizen-readahead-replay.service
 
 # udev daemon killer
 %if %{WITH_UDEVD_KILLER}
-%{_libdir}/systemd/system/default.target.wants/systemd-udevd-kill.timer
 %{_libdir}/systemd/system/systemd-udevd-kill.service
 %{_libdir}/systemd/system/systemd-udevd-kill.timer
+
+%if "%{?tizen_profile_name}" == "mobile"
+%{_libdir}/systemd/system/graphical.target.wants/systemd-udevd-kill.timer
+%elseif "%{?tizen_profile_name}" == "wearable"
+%{_libdir}/systemd/system/default.target.wants/systemd-udevd-kill.timer
+%endif
+
 %endif
 %manifest %{name}.manifest
+
+# mobile & wearable difference
+%if "%{?tizen_profile_name}" == "mobile"
+%{_libdir}/systemd/system/graphical.target.wants/tizen-initial-boot-done.service
+%{_libdir}/systemd/system/graphical.target.wants/tizen-fstrim-user.timer
+%{_libdir}/systemd/system/graphical.target.wants/tizen-readahead-replay.service
+%elseif "%{?tizen_profile_name}" == "wearable"
+%{_libdir}/systemd/system/default.target.wants/tizen-initial-boot-done.service
+%{_libdir}/systemd/system/default.target.wants/tizen-fstrim-user.timer
+%{_libdir}/systemd/system/multi-user.target.wants/tizen-readahead-replay.service
+%endif
+
+%if "%{?tizen_profile_name}" == "mobile"
+%ghost %config(noreplace) %{_sysconfdir}/machine-id
+
+%{_libdir}/udev/rules.d/51-tizen-udev-default.rules
+%{_libdir}/systemd/system/tizen-boot.target
+%{_libdir}/systemd/system/multi-user.target.wants/tizen-boot.target
+%{_libdir}/systemd/system/tizen-system.target
+%{_libdir}/systemd/system/multi-user.target.wants/tizen-system.target
+%{_libdir}/systemd/system/tizen-runtime.target
+%{_libdir}/systemd/system/multi-user.target.wants/tizen-runtime.target
+
+%config(noreplace) %{_sysconfdir}/ghost.conf
+%{_bindir}/ghost
+%{_libdir}/systemd/system/ghost.service
+%{_libdir}/systemd/system/multi-user.target.wants/ghost.service
+
+# sysctl
+%{_libdir}/sysctl.d/50-tizen-default.conf
+
+# cleanup storage
+%{_bindir}/cleanup-storage.sh
+%{_libdir}/systemd/system/basic.target.wants/cleanup-storage.service
+%{_libdir}/systemd/system/timers.target.wants/cleanup-storage.timer
+%{_libdir}/systemd/system/cleanup-storage.service
+%{_libdir}/systemd/system/cleanup-storage.timer
+
+%{_libdir}/systemd/system/tizen-journal-flush.service
+%{_libdir}/systemd/system/graphical.target.wants/tizen-journal-flush.service
+
+%{_libdir}/systemd/system/init-conf.service
+%{_libdir}/systemd/system/sysinit.target.wants/init-conf.service
+%elseif "%{?tizen_profile_name}" == "wearable"
+%{_libdir}/udev/rules.d/51-tizen-udev-default.rules
+%endif
diff --git a/rules/51-tizen-udev-default.rules b/rules/51-tizen-udev-default.rules
new file mode 100644 (file)
index 0000000..ed45cb6
--- /dev/null
@@ -0,0 +1,22 @@
+# Tizen specific additional rules
+
+SUBSYSTEM=="tty", KERNEL=="ptmx", SECLABEL{smack}="*"
+SUBSYSTEM=="tty", KERNEL=="tty", SECLABEL{smack}="*"
+SUBSYSTEM=="tty", KERNEL=="tty[0-9]*", SECLABEL{smack}="*"
+SUBSYSTEM=="vc", KERNEL=="vcs*|vcsa*", SECLABEL{smack}="*"
+KERNEL=="tty[A-Z]*[0-9]|pppox[0-9]*|ircomm[0-9]*|noz[0-9]*|rfcomm[0-9]*", SECLABEL{smack}="*"
+
+# input
+SUBSYSTEM=="input", KERNEL=="mouse*|mice|event*", GROUP="input", MODE="0660"
+
+# video
+KERNEL=="mali", GROUP="video", SECLABEL{smack}="*"
+KERNEL=="slp_global_lock", GROUP="video", SECLABEL{smack}="*"
+SUBSYSTEM=="video4linux", SECLABEL{smack}="*"
+SUBSYSTEM=="drm", SECLABEL{smack}="*"
+
+SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", SECLABEL{smack}="*"
+
+KERNEL=="fuse", SECLABEL{smack}="*"
+
+LABEL="tizen_default_permissions_end"
index cf5a119..2e67a92 100644 (file)
@@ -73,10 +73,17 @@ do_options()
 #                              touch /opt/etc/.hib_capturing # make fastboot image again on next booting
                                /bin/mount -o remount,rw /
                                if [ -f /usr/share/usr_share_locale.squash ]; then
-                                       /bin/umount -l /usr/share/locale
-                                       /bin/rm -rf /usr/share/locale
-                                       /usr/bin/unsquashfs -d /usr/share/locale /usr/share/usr_share_locale.squash
-                                       /bin/rm -rf /usr/share/usr_share_locale.squash
+                                       SIZE=`df | grep rootfs | awk '{print $4}'`
+                                       BLOCK=`du -c /usr/share/locale/ | grep total | awk '{print $1}'`
+                                       if [ $BLOCK -lt $SIZE ]; then
+                                               /bin/umount -l /usr/share/locale
+                                               /bin/rm -rf /usr/share/locale
+                                               /usr/bin/unsquashfs -d /usr/share/locale /usr/share/usr_share_locale.squash
+                                               /bin/rm -rf /usr/share/usr_share_locale.squash
+                                               /usr/bin/find /usr/share/locale -exec /usr/bin/chsmack -a _ {} \;
+                                       else
+                                               echo "Can NOT unsqaushfs because no space in rootfs"
+                                       fi
                                fi
                                exit
                                ;;
diff --git a/scripts/cleanup-storage.sh b/scripts/cleanup-storage.sh
new file mode 100644 (file)
index 0000000..bcbed99
--- /dev/null
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+BE_VERBOSE="false"
+CAN_CLEANALL="false"
+CLEANUP_DIR="/var/log"
+THRESHOLD=90
+WHITE_LIST='! -name 'messages' ! -name 'dlog_main' ! -name 'dlog_system' ! -name 'dlog_radio' ! -name 'Xorg.0.log' ! -name 'system*''
+
+function show_help {
+    echo "
+clean up directory.
+
+usage: ${0##*/} [OPTION...]
+  -h, --help          show help
+  -v, --verbose       provide more detailed output
+  -f, --force         forced clean all if clean failed
+  -d, --directory     clean up directory (default: /var/log)
+  -t, --threshold     clean up threshold (default: 80%)
+"
+}
+
+# Execute getopt
+ARGS=$(getopt -o hvfd:t: -l "help,verbose,force,directory:threshold:" -n "$0" -- "$@");
+
+eval set -- "$ARGS";
+
+while true; do
+    case "$1" in
+        -h|--help)
+            show_help >&2
+            exit 0
+            ;;
+        -v|--verbose)
+            BE_VERBOSE="true"
+            shift
+            ;;
+        -f|--force)
+            CAN_CLEANALL="true"
+            shift
+            ;;
+        -d|--directory)
+            CLEANUP_DIR=$2
+            shift 2
+            ;;
+        -t|--threshold)
+            THRESHOLD=$2
+            shift 2
+            re='^[0-9]+$'
+            if ! [[ $THRESHOLD =~ $re ]] ; then
+                echo "error: threshold value($THRESHOLD) not a number" >&2
+                exit 1
+            fi
+            ;;
+        --)
+            shift;
+            break;
+            ;;
+    esac
+done
+
+if [ $# -ne 0 ]; then
+    show_help >&2
+    exit 1
+fi
+
+function get_status {
+    DF_RESULT=$(/bin/df $CLEANUP_DIR)
+    PERCENT=$(IFS=; echo $DF_RESULT | /bin/awk 'NR==2 {print $5}')
+    PERCENT_N=${PERCENT%\%}
+    MOUNT_POINT=$(IFS=; echo $DF_RESULT | /bin/awk 'NR==2 {print $6}')
+
+    if [ "z$BE_VERBOSE" == "ztrue" ]; then
+        echo "+++ Status of $CLEANUP_DIR +++"
+        echo "Use%: $PERCENT, Mounted at:$MOUNT_POINT"
+    fi
+}
+
+function clean_up {
+        get_status
+        if [ $PERCENT_N -gt $THRESHOLD ];then
+            if [ "z$BE_VERBOSE" == "ztrue" ]; then
+                echo "Do clean up"
+            fi
+            /usr/bin/find $CLEANUP_DIR -type f $WHITE_LIST -exec /bin/rm -f {} \;
+        fi
+    return 0
+}
+
+clean_up
+if [ $? -ne 0 ];then
+    echo "clean up failed"
+fi
index 941afc1..e9f974a 100644 (file)
 #!/bin/sh
 
-EMMC_DEVICE="/dev/mmcblk0"
-RET_PARTX=$(/usr/sbin/partx -s ${EMMC_DEVICE})
-ROOTFS_PART=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | /bin/awk 'tolower($6) == "rootfs" {print $1}')
-SYSTEM_DATA_PART=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | /bin/awk 'tolower($6) == "system-data" {print $1}')
-USER_PART=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | /bin/awk 'tolower($6) == "user" {print $1}')
-CSC_PART=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | /bin/awk 'tolower($6) == "csc" {print $1}')
-MODULES_PART=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | /bin/awk 'tolower($6) == "module" {print $1}')
-
 TIZEN_LABEL="tizen"
 
-# rootfs partition
-PART_LABEL="$(/sbin/e2label $ROOTFS_PART)"
-if [ "z${PART_LABEL}" != "z${TIZEN_LABEL}" ]; then
-    /bin/mount -o remount,rw /
-    /sbin/resize2fs -f $ROOTFS_PART
-    /bin/mount -o remount,ro /
-    /sbin/e2label $ROOTFS_PART $TIZEN_LABEL
-fi
+function do_ext4 {
+    EMMC_DEVICE="/dev/mmcblk0"
+    RET_PARTX=$(/usr/sbin/partx -s ${EMMC_DEVICE})
+    ROOTFS_PART=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | /bin/awk 'tolower($6) == "rootfs" {print $1}')
+    SYSTEM_DATA_PART=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | /bin/awk 'tolower($6) == "system-data" {print $1}')
+    USER_PART=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | /bin/awk 'tolower($6) == "user" {print $1}')
+    CSC_PART=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | /bin/awk 'tolower($6) == "csc" {print $1}')
+    MODULES_PART=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | /bin/awk 'tolower($6) == "module" {print $1}')
 
-# system-data partition
-PART_LABEL="$(/sbin/e2label $SYSTEM_DATA_PART)"
-if [ "z${PART_LABEL}" != "z${TIZEN_LABEL}" ]; then
-    /bin/grep "$SYSTEM_DATA_PART" /proc/mounts || /sbin/e2fsck -y -f "$SYSTEM_DATA_PART"
-    /sbin/resize2fs -f $SYSTEM_DATA_PART
-    if [ $? -ne 0 ]; then
-        /sbin/e2fsck -y -f $SYSTEM_DATA_PART
+    # rootfs partition
+    PART_LABEL="$(/sbin/e2label $ROOTFS_PART)"
+    if [ "z${PART_LABEL}" != "z${TIZEN_LABEL}" ]; then
+        /bin/mount -o remount,rw /
+        /sbin/resize2fs -f $ROOTFS_PART
+        /bin/mount -o remount,ro /
+        /sbin/e2label $ROOTFS_PART $TIZEN_LABEL
+    fi
+
+    # system-data partition
+    PART_LABEL="$(/sbin/e2label $SYSTEM_DATA_PART)"
+    if [ "z${PART_LABEL}" != "z${TIZEN_LABEL}" ]; then
+        /bin/grep "$SYSTEM_DATA_PART" /proc/mounts || /sbin/e2fsck -y -f "$SYSTEM_DATA_PART"
         /sbin/resize2fs -f $SYSTEM_DATA_PART
+        if [ $? -ne 0 ]; then
+            /sbin/e2fsck -y -f $SYSTEM_DATA_PART
+            /sbin/resize2fs -f $SYSTEM_DATA_PART
+        fi
+        /sbin/e2label $SYSTEM_DATA_PART $TIZEN_LABEL
     fi
-    /sbin/e2label $SYSTEM_DATA_PART $TIZEN_LABEL
-fi
 
-# CSC partition
-PART_LABEL="$(/sbin/e2label $CSC_PART)"
-if [ "z${PART_LABEL}" != "z${TIZEN_LABEL}" ]; then
-    /bin/grep "$CSC_PART" /proc/mounts || /sbin/e2fsck -y -f "$CSC_PART"
-    /sbin/resize2fs -f $CSC_PART
-    if [ $? -ne 0 ]; then
-        /sbin/e2fsck -y -f $CSC_PART
+    # CSC partition
+    PART_LABEL="$(/sbin/e2label $CSC_PART)"
+    if [ "z${PART_LABEL}" != "z${TIZEN_LABEL}" ]; then
+        /bin/grep "$CSC_PART" /proc/mounts || /sbin/e2fsck -y -f "$CSC_PART"
         /sbin/resize2fs -f $CSC_PART
+        if [ $? -ne 0 ]; then
+            /sbin/e2fsck -y -f $CSC_PART
+            /sbin/resize2fs -f $CSC_PART
+        fi
+        /sbin/e2label $CSC_PART $TIZEN_LABEL
     fi
-    /sbin/e2label $CSC_PART $TIZEN_LABEL
-fi
 
-# user partition
-PART_LABEL="$(/sbin/e2label $USER_PART)"
-if [ "z${PART_LABEL}" != "z${TIZEN_LABEL}" ]; then
-    /bin/grep "$USER_PART" /proc/mounts || /sbin/e2fsck -y -f "$USER_PART"
-    /sbin/resize2fs -f $USER_PART
-    if [ $? -ne 0 ]; then
-        /sbin/e2fsck -y -f $USER_PART
+    # user partition
+    PART_LABEL="$(/sbin/e2label $USER_PART)"
+    if [ "z${PART_LABEL}" != "z${TIZEN_LABEL}" ]; then
+        /bin/grep "$USER_PART" /proc/mounts || /sbin/e2fsck -y -f "$USER_PART"
         /sbin/resize2fs -f $USER_PART
+        if [ $? -ne 0 ]; then
+            /sbin/e2fsck -y -f $USER_PART
+            /sbin/resize2fs -f $USER_PART
+        fi
+        /sbin/e2label $USER_PART $TIZEN_LABEL
     fi
-    /sbin/e2label $USER_PART $TIZEN_LABEL
-fi
 
-# Mount system-data(/opt) partition.
-if [ "z$SYSTEM_DATA_PART" != "z${EMMC_DEVICE}p" ]; then
-    CHECK_ERR=`/sbin/dumpe2fs $SYSTEM_DATA_PART | /bin/grep "Filesystem state" | /bin/grep "error"`
-    if [ "z$CHECK_ERR" != "z" ]; then
+    # Mount system-data(/opt) partition.
+    if [ "z$SYSTEM_DATA_PART" != "z${EMMC_DEVICE}p" ]; then
         /sbin/e2fsck -y -f $SYSTEM_DATA_PART
+        /bin/mount -t $FS_TYPE $SYSTEM_DATA_PART /opt -o errors=panic,nosuid
+        # If /opt partition is not mounted by crashing file system,
+        # then check partition using e2fsck and re-mount it.
+        if [ $? -ne 0 ]; then
+            /sbin/e2fsck -y -f $SYSTEM_DATA_PART
+            /bin/mount -t $FS_TYPE $SYSTEM_DATA_PART /opt -o errors=panic,nosuid
+        fi
     fi
-    /bin/mount -t ext4 $SYSTEM_DATA_PART /opt -o errors=panic,nosuid
-    # If /opt partition is not mounted by crashing file system,
-    # then check partition using e2fsck and re-mount it.
-    if [ $? -ne 0 ]; then
-        /sbin/e2fsck -y -f $SYSTEM_DATA_PART
-        /bin/mount -t ext4 $SYSTEM_DATA_PART /opt -o errors=panic,nosuid
+
+    # Mount modules(/lib/modules) partition.
+    if [ "z$MODULES_PART" != "z${EMMC_DEVICE}p" ]; then
+        /bin/mount -t $FS_TYPE $MODULES_PART /lib/modules -o ro &
     fi
-fi
+}
+
+function do_ubi {
+    UBI_DEVICE="ubi0"
+    ROOTFS_PART=${UBI_DEVICE}:rootfs
+    SYSTEM_DATA_PART=${UBI_DEVICE}:systemData
+    USER_PART=${UBI_DEVICE}:user
+    CSC_PART=${UBI_DEVICE}:csc
+    MODULES_PART=${UBI_DEVICE}:module
+
+    # Mount system-data(/opt) partition.
+    /bin/mount -t $FS_TYPE $SYSTEM_DATA_PART /opt -o rw
+}
 
-# Mount modules(/lib/modules) partition.
-if [ "z$MODULES_PART" != "z${EMMC_DEVICE}p" ]; then
-    /bin/mount -t ext4 $MODULES_PART /lib/modules -o ro &
+# !!! Start from here !!!
+if [ ! -e /etc/machine-id ]; then
+    /bin/mount -o remount,rw /
+    /usr/bin/systemd-machine-id-setup
+    /bin/mount -o remount,ro /
 fi
+
+for arg in $(/bin/cat /proc/cmdline); do
+    case "$arg" in
+        rootfstype=*)
+            FS_TYPE="${arg//rootfstype=}"
+            break;
+            ;;
+    esac
+done
+
+case $FS_TYPE in
+    ext4)
+        do_ext4;
+        ;;
+    ubifs)
+        do_ubi;
+        ;;
+esac
index 2ee30eb..9aab820 100644 (file)
@@ -1,20 +1,21 @@
 #!/bin/sh
 
 if [ "$#" -ne 1 ];then
-        echo "Argument was missed."
-        exit 1
+       echo "Argument was missed."
+       exit 1
 fi
 
 CHARGE_NOW_FILE=`/usr/bin/find /sys/devices -path */power_supply/battery/charge_now`
 if [ "x$CHARGE_NOW_FILE" == "x" ]; then
-        echo "Can not find 'charge_now'."
-        exit 1
+       echo "Can not find 'charge_now'."
+       exit 1
 else
-        CHARGE_NOW_VALUE=`/bin/cat $CHARGE_NOW_FILE`
+       CHARGE_NOW_VALUE=`/bin/cat $CHARGE_NOW_FILE`
 fi
 
 if [ "$CHARGE_NOW_VALUE" -gt 0 ];then
-        /sbin/fstrim $*
+       echo "Do fstrim."
+       /sbin/fstrim $*
 else
-        exit 1
+       echo "Not on charging."
 fi
diff --git a/src/ghost/ghost.c b/src/ghost/ghost.c
new file mode 100644 (file)
index 0000000..e9d0bc0
--- /dev/null
@@ -0,0 +1,656 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * system-plugin-common
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include "util.h"
+#include "fileio.h"
+#include "conf-parser.h"
+#include "systemd.h"
+
+#define GHOST_CONF              "/etc/ghost.conf"
+#define GHOST_DIR               "/var/log/ghost"
+#define GHOST_BOOT_DIR          GHOST_DIR "/boot"
+#define GHOST_BOOTCOUNT         GHOST_BOOT_DIR "/bootcount"
+#define GHOST_LINK_CURRENT      GHOST_BOOT_DIR "/current"
+
+#define GHOST_CURRENT_BOOTTIME  GHOST_LINK_CURRENT "/boottime"
+#define GHOST_CURRENT_PLOTCHART GHOST_LINK_CURRENT "/plotchart.svg"
+
+#define GHOST_TIME_OUT         120
+
+#define GHOST_THRESHOLD_DISK_USAGE_RATIO 3
+
+int bootcount;
+int ghost_mask;
+bool arg_boottime = true;
+bool arg_bootchart = false;
+bool arg_plotchart = false;
+
+enum GhostMask {
+        MASK_BOOTTIME = 0,
+        MASK_PLOTCHART,
+        MASK_BOOTCHART,
+};
+
+static int parse_config_file(void) {
+        const ConfigTableItem items[] = {
+                { "Ghost",      "boottime",     config_parse_bool,      0,      &arg_boottime   },
+                { "Ghost",      "plotchart",    config_parse_bool,      0,      &arg_plotchart  },
+                { "Ghost",      "bootchart",    config_parse_bool,      0,      &arg_bootchart  },
+                { NULL,         NULL,           NULL,                   0,      NULL            }
+        };
+
+        int r;
+
+        r = config_parse(GHOST_CONF, (void*) items);
+        if (r < 0) {
+                fprintf(stderr, "Failed to parse configuration file: %s\n", strerror(-r));
+                return r;
+        }
+
+        return 0;
+}
+
+static int get_bootcount_from_file(int *count) {
+        _cleanup_free_ char *s = NULL;
+        int r;
+
+        r = read_one_line_file(GHOST_BOOTCOUNT, &s);
+        if (r < 0 && errno != ENOENT)
+                return r;
+
+        *count = (s) ? atoi(s) : 0;
+        return 0;
+}
+
+static int get_bootcount_from_dir(int *count) {
+        _cleanup_closedir_ DIR *dir = NULL;
+        struct dirent *de;
+        int c = 0;
+
+        dir = opendir(GHOST_BOOT_DIR);
+        if (!dir)
+                return errno;
+
+        FOREACH_DIRENT(de, dir, return -errno) {
+                if (de->d_type != DT_DIR)
+                        continue;
+
+                c = atoi(de->d_name) > c ? atoi(de->d_name) : c;
+        }
+
+        *count = c;
+        return 0;
+}
+
+static int update_bootcount(void) {
+        _cleanup_free_ char *count = NULL;
+        int r, from_dir = 0, from_file = 0;
+
+        r = get_bootcount_from_file(&from_file);
+        if (r < 0)
+                return r;
+
+        r = get_bootcount_from_dir(&from_dir);
+        if (r < 0)
+                return r;
+
+        bootcount = from_file > from_dir ? from_file : from_dir;
+
+        r = asprintf(&count, "%d", ++bootcount);
+        if (r < 0)
+                return r;
+
+        r = write_string_file(GHOST_BOOTCOUNT, count);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+
+struct df_info {
+        char device[30];
+        int blocks;
+        int used;
+        int available;
+        int use_ratio;
+        char mount_on[PATH_MAX];
+};
+
+#define GHOST_CURRENT_DISKINFO GHOST_LINK_CURRENT "/diskinfo"
+
+static void ghost_parse_df_info(struct df_info *info, char *buf) {
+        char *p = buf;
+        char t[30];
+        size_t len;
+
+        /* Filesystem */
+        len = strcspn(p, WHITESPACE);
+        snprintf(info->device, len+1, "%s", p);
+        p += len + strspn(p+len, WHITESPACE);
+
+        /* 1K-blocks */
+        len = strcspn(p, WHITESPACE);
+        snprintf(t, len+1, "%s", p);
+        info->blocks = atoi(t);
+        p += len + strspn(p+len, WHITESPACE);
+
+        /* Used */
+        len = strcspn(p, WHITESPACE);
+        snprintf(t, len+1, "%s", p);
+        info->used = atoi(t);
+        p += len + strspn(p+len, WHITESPACE);
+
+        /* Available */
+        len = strcspn(p, WHITESPACE);
+        snprintf(t, len+1, "%s", p);
+        info->available = atoi(t);
+        p += len + strspn(p+len, WHITESPACE);
+
+        /* Use% */
+        len = strcspn(p, WHITESPACE);
+        snprintf(t, len, "%s", p);
+        info->use_ratio = atoi(t);
+        p += len + strspn(p+len, WHITESPACE);
+
+        /* Mounted on */
+        len = strcspn(p, NEWLINE);
+        snprintf(info->mount_on, len+1, "%s", p);
+}
+
+static int ghost_get_disk_info(struct df_info *info) {
+        int pipefd[2];
+        int status;
+        int r;
+
+        pipe(pipefd);
+        if(fork() == 0) {
+                char * const args[] = {"/bin/df", GHOST_DIR, NULL};
+
+                close(pipefd[0]);
+                dup2(pipefd[1], 1);
+                dup2(pipefd[1], 2);
+                usleep(1000);
+                execvp(args[0], args);
+
+                close(pipefd[1]);
+                _exit(1);
+        } else {
+                char buf[LINE_MAX*2];
+                char *p = buf;
+
+                close(pipefd[1]);
+                wait(&status);
+                if (!WIFEXITED(status))
+                        return -WEXITSTATUS(status);
+
+                /* size of buf maybe bigger than df output */
+                r = read(pipefd[0], buf, sizeof(buf));
+                if (r < 0)
+                        return -errno;
+
+                /* discard first line */
+                p += strcspn(p, NEWLINE)+1;
+                truncate_nl(p);
+
+                ghost_parse_df_info(info, p);
+        }
+
+        return 0;
+}
+
+static int ghost_get_disk_usage(int *usage) {
+        int pipefd[2];
+        int status;
+        int r;
+
+        pipe(pipefd);
+        if(fork() == 0) {
+                char * const args[] = {"/usr/bin/du", "-s", GHOST_DIR, NULL};
+
+                close(pipefd[0]);
+                dup2(pipefd[1], 1);
+                dup2(pipefd[1], 2);
+                usleep(1000);
+                execvp(args[0], args);
+
+                close(pipefd[1]);
+                _exit(1);
+        } else {
+                char buf[LINE_MAX];
+
+                close(pipefd[1]);
+                wait(&status);
+                if (!WIFEXITED(status))
+                        return -WEXITSTATUS(status);
+
+                /* size of buf maybe bigger than du output */
+                r = read(pipefd[0], buf, sizeof(buf));
+                if (r < 0)
+                        return -errno;
+
+                buf[strcspn(buf, WHITESPACE)] = 0;
+                *usage = atoi(buf);
+        }
+
+        return 0;
+}
+
+static gint sort_num_str_by_ascending(gconstpointer a, gconstpointer b) {
+        return atoi(a) - atoi(b);
+}
+
+static int generate_dir_list(GList **list, DIR *dir) {
+        struct dirent *de;
+        GList *l = NULL;
+
+        FOREACH_DIRENT(de, dir, goto out) {
+                if (de->d_type != DT_DIR)
+                        continue;
+
+                l = g_list_prepend(l, de->d_name);
+        }
+
+        l = g_list_sort(l, sort_num_str_by_ascending);
+        *list = l;
+        return 0;
+
+out:
+        if (l)
+            g_list_free(l);
+        return -errno;
+}
+
+static int check_threshhold(void) {
+        _cleanup_closedir_ DIR *dir = NULL;
+        _cleanup_free_ struct df_info *df = NULL;
+        int r, usage;
+        GList *list = NULL, *head = NULL;
+
+        df = new0(struct df_info, 1);
+        r = ghost_get_disk_info(df);
+        if (r < 0) {
+                fprintf(stderr, "Failed to get disk info\n");
+                return r;
+        }
+
+        r = ghost_get_disk_usage(&usage);
+        if (r < 0) {
+                fprintf(stderr, "Failed to get disk usage\n");
+                return r;
+        }
+
+        if ((usage * 100 / df->blocks) < GHOST_THRESHOLD_DISK_USAGE_RATIO)
+                return 0;
+
+        dir = opendir(GHOST_BOOT_DIR);
+        if (!dir) {
+                fprintf(stderr, "Failed to open dir: %s", GHOST_BOOT_DIR);
+                return -errno;
+        }
+
+        r = generate_dir_list(&list, dir);
+        if (r < 0)
+                goto finish;
+
+        do {
+                _cleanup_free_ char *path = NULL;
+
+                head = g_list_first(list);
+                r = asprintf(&path, "%s/%s", GHOST_BOOT_DIR, (char *)head->data);
+                if (r < 0)
+                        goto finish;
+
+                r = rmdir_recursive(path);
+                if (r < 0) {
+                        fprintf(stderr, "Failed to delete directory: %s\n", dir);
+                        r = -errno;
+                        goto finish;
+                }
+
+                list = g_list_remove(list, list->data);
+
+                r = ghost_get_disk_usage(&usage);
+                if (r < 0) {
+                        fprintf(stderr, "Failed to get disk usage\n");
+                        goto finish;
+                }
+        } while((usage * 100 / df->blocks) >= GHOST_THRESHOLD_DISK_USAGE_RATIO);
+
+        r = 0;
+finish:
+        g_list_free(list);
+        return r;
+}
+
+static int prepare_working_dir(void) {
+        _cleanup_free_ char *path = NULL, *count = NULL;
+        int r;
+
+        r = asprintf(&path, "%s/%d", GHOST_BOOT_DIR, bootcount);
+        if (r < 0)
+                return r;
+
+        r = mkdir(path, 0755);
+        if (r < 0)
+                return -errno;
+
+        r = unlink(GHOST_LINK_CURRENT);
+        if (r < 0 && errno != ENOENT)
+                return -errno;
+
+        r = asprintf(&count, "%d", bootcount);
+        if (r < 0)
+                return r;
+
+        r = symlink(count, GHOST_LINK_CURRENT);
+        if (r < 0)
+                return -errno;
+
+        return 0;
+}
+
+static int set_loopmask(void) {
+        int mask = 0;
+
+        return mask =
+                (arg_boottime ? (0x01) << MASK_BOOTTIME : 0x00) |
+                (arg_plotchart ? (0x01) << MASK_PLOTCHART : 0x00) |
+                (arg_bootchart ? (0x01) << MASK_BOOTCHART : 0x00);
+}
+
+static int get_boottime_checkpoint(void) {
+        _cleanup_free_ char *result = NULL, *active_state = NULL, *platform_sec = NULL;
+        unsigned int exec_main_pid = 0, main_pid = 0;
+        unsigned long long inactive_enter_timestamp_monotonic, exec_main_exit_timestamp_monotonic;
+        int r, exec_main_code = 0;
+
+        if (!(ghost_mask & 0x01 << MASK_BOOTTIME))
+                return 0;
+
+        r = systemd_get_unit_property_as_string("boot-animation.service",
+                                                "ActiveState",
+                                                &active_state);
+        if (r < 0)
+                return -r;
+
+        r = systemd_get_unit_property_as_uint64("boot-animation.service",
+                                                "InactiveEnterTimestampMonotonic",
+                                                &inactive_enter_timestamp_monotonic);
+        if (r < 0)
+                return -r;
+
+        r = systemd_get_service_property_as_string("boot-animation.service",
+                                                   "Result",
+                                                   &result);
+        if (r < 0)
+                return -r;
+
+        if (streq(active_state, "inactive") &&
+            inactive_enter_timestamp_monotonic != 0 &&
+            streq(result, "success")) {
+                ghost_mask &= ~(0x01 << MASK_BOOTTIME);
+                r = systemd_get_service_property_as_uint64("boot-animation.service",
+                                                           "ExecMainExitTimestampMonotonic",
+                                                           &exec_main_exit_timestamp_monotonic);
+                if (r < 0)
+                        return -r;
+
+                r = asprintf(&platform_sec, "platform(sec): %.2lf",
+                             ((float)(exec_main_exit_timestamp_monotonic/1000)/1000));
+                if (r < 0)
+                        return r;
+
+                r = write_string_file(GHOST_CURRENT_BOOTTIME, platform_sec);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+static int ghost_processing_plotchart(void) {
+        _cleanup_free_ char *active_state = NULL;
+        pid_t my_pid, parent_pid, child_pid;
+        int r, status;
+        unsigned int jobs;
+
+        if (!(ghost_mask & 0x01 << MASK_PLOTCHART))
+                return 0;
+
+        r = systemd_get_unit_property_as_string("default.target",
+                                                "ActiveState",
+                                                &active_state);
+        if (r < 0)
+                return -r;
+
+        if (!streq(active_state, "active"))
+                return 0;
+
+        r = systemd_get_manager_property_as_uint32(DBUS_INTERFACE_SYSTEMD_MANAGER,
+                                                   "NJobs",
+                                                   &jobs);
+        if (r < 0)
+                return -r;
+
+        if (jobs)
+                return 0;
+
+        if((child_pid = fork()) < 0 ) {
+                perror("fork failure");
+                exit(1);
+        }
+
+        if(child_pid == 0) {
+                char * const args[] = {"/usr/bin/systemd-analyze", "plot", NULL};
+                int fd = open(GHOST_CURRENT_PLOTCHART, O_RDWR | O_CREAT, 0644);
+
+                if (fd < 0)
+                        _exit(EXIT_FAILURE);
+
+                dup2(fd, 1);
+                execvp(args[0], args);
+
+                close(fd);
+                _exit(1);
+        } else {
+                wait(&status);
+
+                if (WIFEXITED(status))
+                        ghost_mask &= ~(0x01 << MASK_PLOTCHART);
+        }
+        return 0;
+}
+
+static bool is_bootchart_set_as_init(void) {
+        _cleanup_free_ char *cmdline  = NULL;
+        char *w, *state;
+        size_t l;
+        bool contained = false;
+        int r;
+
+        if (read_one_line_file("/proc/cmdline", &cmdline) < 0) {
+                fprintf(stderr, "Failed to read /proc/cmdline.\n");
+                return false;
+        }
+
+        FOREACH_WORD(w, l, cmdline, state)
+                if (strneq("init=/usr/lib/systemd/systemd-bootchart", w, l))
+                        return true;
+
+        return false;
+}
+
+static int ghost_processing_bootchart(pid_t bootchart_pid) {
+        _cleanup_free_ char *proc_pid = NULL, *bootchart_path = NULL;
+        _cleanup_closedir_ DIR *dir = NULL;
+        struct dirent *de;
+        int r;
+
+        if (!(ghost_mask & 0x01 << MASK_BOOTCHART))
+                return 0;
+
+        /* If bootchart_pid is 0, then maybe ghost is started after
+         * bootchart had finished. So safe and goto copy. */
+        if (bootchart_pid == 0)
+                goto copy_bootchart;
+
+        r = asprintf(&proc_pid, "/proc/%d", bootchart_pid);
+        if (r < 0)
+                return r;
+
+        /* Do NOT be confused for the return check. We hope the
+         * bootchart is finished to get the result. So its process id
+         * should be disappeared. */
+        r = access(proc_pid, F_OK);
+        if (r == 0)
+                return 0;
+
+        if (r < 0 &&
+            errno != ENOENT)
+                return -errno;
+
+copy_bootchart:
+        dir = opendir("/run/log");
+        if (!dir)
+                return -errno;
+
+        FOREACH_DIRENT(de, dir, return -errno) {
+                if (de->d_type != DT_REG)
+                        continue;
+
+                if (startswith(de->d_name, "bootchart-")) {
+                        r = asprintf(&bootchart_path, "/run/log/%s", de->d_name);
+                        if (r < 0)
+                                continue;
+
+                        r = do_copy(bootchart_path, GHOST_LINK_CURRENT, NULL);
+                        if (r < 0) {
+                                fprintf(stderr, "Failed to copy bootchart.\n");
+                                continue;
+                        }
+                }
+        }
+
+        ghost_mask &= ~(0x01 << MASK_BOOTCHART);
+        return 0;
+}
+
+static int ghost_loop(void) {
+        int sec = 0;
+        int r;
+        bool do_bootchart;
+        pid_t pid_of_bootchart;
+
+        do_bootchart = is_bootchart_set_as_init();
+        if (do_bootchart)
+                pid_of_bootchart = pid_of("systemd-bootchart");
+        else
+                ghost_mask &= ~(0x01 << MASK_BOOTCHART);
+
+        while (ghost_mask) {
+                /* check boot-animation finished */
+                r = get_boottime_checkpoint();
+                if (r < 0)
+                        return r;
+
+                /* check booting completed(default.target) */
+                r = ghost_processing_plotchart();
+                if (r < 0)
+                        return r;
+
+                /* If init=/usr/lib/systemd/systemd-bootchar is
+                 * contained at kernel command line then the bootchart
+                 * will be copied to ghost current working
+                 * directory. */
+                if(do_bootchart) {
+                        r = ghost_processing_bootchart(pid_of_bootchart);
+                        if (r < 0)
+                                return r;
+                }
+
+                sleep(1);
+                if (sec++ > GHOST_TIME_OUT) {
+                        fprintf(stderr, "ghost loop time(almost %dsec) over.\n",
+                                GHOST_TIME_OUT);
+                        break;
+                }
+        }
+
+        return 0;
+}
+
+int main(int argc, char *argv[]) {
+        int r;
+
+        r = parse_config_file();
+        if (r < 0)
+                return r;
+
+        if (do_mkdir(GHOST_BOOT_DIR, 0755) && errno != EEXIST) {
+                fprintf(stderr, "Failed to create ghost directory: %s\n", GHOST_BOOT_DIR);
+                return -errno;
+        }
+
+        /* boot count update */
+        r = update_bootcount();
+        if (r < 0) {
+                fprintf(stderr, "Failed to update bootcount: %s\n", strerror(-r));
+                return r;
+        } else
+                fprintf(stdout, "[Ghost] Now, %d%s boot.\n",
+                        bootcount,
+                        bootcount == 1 ? "st" :
+                        bootcount == 2 ? "nd" :
+                        bootcount == 3 ? "rd" : "th");
+
+        r = check_threshhold();
+        if (r < 0) {
+                fprintf(stderr, "Failed to check threshold: %s\n", strerror(-r));
+                return r;
+        }
+
+        r = prepare_working_dir();
+        if (r < 0) {
+                fprintf(stderr, "Failed to make current boot dir: %s\n", strerror(-r));
+                return r;
+        }
+
+        ghost_mask = set_loopmask();
+        r = ghost_loop();
+        if (r < 0)
+                return r;
+
+        return 0;
+}
diff --git a/src/ghost/ghost.conf.m4 b/src/ghost/ghost.conf.m4
new file mode 100644 (file)
index 0000000..5815921
--- /dev/null
@@ -0,0 +1,10 @@
+[Ghost]
+m4_ifdef(`WITH_ENGMODE',
+`#output=<folder name, defaults to /var/log/ghost>
+boottime=y
+plotchart=y
+bootchart=y',
+`#output=<folder name, defaults to /var/log/ghost>
+#boottime=y
+#plotchart=n
+#bootchart=n')
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
new file mode 100644 (file)
index 0000000..5f38eee
--- /dev/null
@@ -0,0 +1,243 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * system-plugin-common
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * 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 <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <limits.h>
+
+#include "util.h"
+#include "conf-parser.h"
+
+#define MAX_SECTION     64
+
+static int config_table_lookup(
+                void *table,
+                const char *section,
+                const char *lvalue,
+                ConfigParserCallback *func,
+                int *ltype,
+                void **data) {
+
+        ConfigTableItem *t;
+
+        assert(table);
+        assert(lvalue);
+        assert(func);
+        assert(ltype);
+        assert(data);
+
+        for (t = table; t->lvalue; t++) {
+
+                if (!streq(lvalue, t->lvalue))
+                        continue;
+
+                if (!streq_ptr(section, t->section))
+                        continue;
+
+                *func = t->cb;
+                *ltype = t->ltype;
+                *data = t->data;
+                return 1;
+        }
+
+        return 0;
+}
+
+/* Run the user supplied parser for an assignment */
+static int config_parse_table(
+                const char *filename,
+                unsigned line,
+                void *table,
+                const char *section,
+                const char *lvalue,
+                const char *rvalue) {
+
+        ConfigParserCallback cb = NULL;
+        int ltype = 0;
+        void *data = NULL;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+
+        r = config_table_lookup(table,
+                                section,
+                                lvalue,
+                                &cb,
+                                &ltype,
+                                &data);
+        if (r <= 0)
+                return r;
+
+        if (cb)
+                return cb(filename,
+                          line,
+                          section,
+                          lvalue,
+                          ltype,
+                          rvalue,
+                          data);
+
+        return 0;
+}
+
+int config_parse(
+                const char *filename,
+                void *table) {
+
+        _cleanup_fclose_ FILE *f = NULL;
+        char *sections[MAX_SECTION] = { 0 };
+        char *section = NULL, *n, *e, l[LINE_MAX];
+        size_t len;
+        int i, r, num_section = 0;
+        bool already;
+        unsigned line = 0;
+
+        assert(filename);
+
+        f = fopen(filename, "r");
+        if (!f) {
+                fprintf(stderr, "Error: Failed to open file %s\n", filename);
+                return -errno;
+        }
+
+        while (!feof(f)) {
+                _cleanup_free_ char *lvalue = NULL, *rvalue = NULL;
+
+                if (fgets(l, LINE_MAX, f) == NULL) {
+                        if (feof(f))
+                                break;
+
+                        fprintf(stderr, "Error: Failed to parse configuration file '%s': %m\n", filename);
+                        r = -errno;
+                        goto finish;
+                }
+
+                line++;
+                truncate_nl(l);
+
+                if (strchr(COMMENTS NEWLINE, *l))
+                        continue;
+
+                if (*l == '[') {
+                        len = strlen(l);
+                        if (l[len-1] != ']') {
+                                fprintf(stderr, "Error: Invalid section header: %s\n", l);
+                                r = -EBADMSG;
+                                goto finish;
+                        }
+
+                        n = strndup(l+1, len-2);
+                        if (!n) {
+                                r = -ENOMEM;
+                                goto finish;
+                        }
+
+                        already = false;
+                        for (i = 0; i < num_section; i++) {
+                                if (streq(n, sections[i])) {
+                                        section = sections[i];
+                                        already = true;
+                                        free(n);
+                                        break;
+                                }
+                        }
+
+                        if (already)
+                                continue;
+
+                        section = n;
+                        sections[num_section] = n;
+                        num_section++;
+                        if (num_section > MAX_SECTION) {
+                                fprintf(stderr, "Error: max number of section reached: %d\n", num_section);
+                                r = -EOVERFLOW;
+                                goto finish;
+                        }
+
+                        continue;
+                }
+
+                if (!section)
+                        continue;
+
+                e = strchr(l, '=');
+                if (e == NULL) {
+                        fprintf(stderr, "Warning: config: no '=' character in line '%s'.\n", l);
+                        continue;
+                }
+
+                lvalue = strndup(l, e-l);
+                strstrip(lvalue);
+
+                rvalue = strdup(e+1);
+                strstrip(rvalue);
+
+                r = config_parse_table(filename,
+                                       line,
+                                       table,
+                                       section,
+                                       lvalue,
+                                       rvalue);
+                if (r < 0)
+                        goto finish;
+        }
+
+        r = 0;
+
+finish:
+        for (i=0; i<num_section; i++)
+                if (sections[i])
+                        free(sections[i]);
+
+        return r;
+}
+
+int config_parse_bool(
+                const char *filename,
+                unsigned line,
+                const char *section,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data) {
+
+        int k;
+        bool *b = data;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        k = parse_boolean(rvalue);
+        if (k < 0) {
+                fprintf(stderr, "Failed to parse boolean value, ignoring: %s\n", rvalue);
+                return 0;
+        }
+
+        *b = !!k;
+        return 0;
+}
diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h
new file mode 100644 (file)
index 0000000..9ccfc08
--- /dev/null
@@ -0,0 +1,62 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * system-plugin-common
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * 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
+
+#include <stdio.h>
+#include <stdbool.h>
+
+/* Prototype for a parser for a specific configuration setting */
+typedef int (*ConfigParserCallback)(
+                const char *filename,
+                unsigned line,
+                const char *section,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data);
+
+/* Wraps information for parsing a specific configuration variable, to
+ * be stored in a simple array */
+typedef struct ConfigTableItem {
+        const char *section;            /* Section */
+        const char *lvalue;             /* Name of the variable */
+        ConfigParserCallback cb;        /* Function that is called to
+                                         * parse the variable's
+                                         * value */
+        int ltype;                      /* Distinguish different
+                                         * variables passed to the
+                                         * same callback */
+        void *data;                     /* Where to store the
+                                         * variable's data */
+} ConfigTableItem;
+
+int config_parse(
+                const char *filename,
+                void *table);
+
+int config_parse_bool(
+                const char *filename,
+                unsigned line,
+                const char *section,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data);
diff --git a/src/shared/dbus-common.h b/src/shared/dbus-common.h
new file mode 100644 (file)
index 0000000..387f961
--- /dev/null
@@ -0,0 +1,27 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * system-plugin-common
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * 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
+
+#include <dbus/dbus.h>
+
+#define DBUS_INTERFACE_DBUS_PROPERTIES          DBUS_SERVICE_DBUS ".Properties"
+#define DBUS_INTERFACE_DBUS_PEER                DBUS_SERVICE_DBUS ".Peer"
+#define DBUS_INTERFACE_DBUS_INTROSPECTABLE      DBUS_SERVICE_DBUS ".Introspectable"
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
new file mode 100644 (file)
index 0000000..83ef0b6
--- /dev/null
@@ -0,0 +1,90 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * system-plugin-common
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * 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 <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "fileio.h"
+#include "util.h"
+
+int write_string_to_file(FILE *f, const char *line) {
+        errno = 0;
+        fputs(line, f);
+        if (!endswith(line, "\n"))
+                fputc('\n', f);
+
+        fflush(f);
+
+        if (ferror(f))
+                return errno ? -errno : -EIO;
+
+        return 0;
+}
+
+int write_string_file(const char *fn, const char *line) {
+        _cleanup_fclose_ FILE *f = NULL;
+
+        assert(fn);
+        assert(line);
+
+        f = fopen(fn, "we");
+        if (!f)
+                return -errno;
+
+        return write_string_to_file(f, line);
+}
+
+int read_one_line_from_file(FILE *f, char **line) {
+        char t[LINE_MAX], *c;
+
+        errno = 0;
+
+        if (!fgets(t, sizeof(t), f)) {
+
+                if (ferror(f))
+                        return errno ? -errno : -EIO;
+
+                t[0] = 0;
+        }
+
+        c = strdup(t);
+        if (!c)
+                return -ENOMEM;
+
+        *line = truncate_nl(c);
+        return 0;
+}
+
+int read_one_line_file(const char *fn, char **line) {
+        _cleanup_fclose_ FILE *f = NULL;
+        char t[LINE_MAX], *c;
+
+        assert(fn);
+        assert(line);
+
+        f = fopen(fn, "re");
+        if (!f)
+                return -errno;
+
+        return read_one_line_from_file(f, line);
+}
diff --git a/src/shared/fileio.h b/src/shared/fileio.h
new file mode 100644 (file)
index 0000000..1713535
--- /dev/null
@@ -0,0 +1,28 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * system-plugin-common
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * 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
+
+#include <stdio.h>
+
+int write_string_to_file(FILE *f, const char *line);
+int write_string_file(const char *fn, const char *line);
+int read_one_line_from_file(FILE *f, char **line);
+int read_one_line_file(const char *fn, char **line);
diff --git a/src/shared/macro.h b/src/shared/macro.h
new file mode 100644 (file)
index 0000000..5770d4b
--- /dev/null
@@ -0,0 +1,24 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * system-plugin-common
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * 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
+
+#define _pure_ __attribute__ ((pure))
+#define _cleanup_(x) __attribute__((cleanup(x)))
diff --git a/src/shared/systemd.c b/src/shared/systemd.c
new file mode 100644 (file)
index 0000000..c484095
--- /dev/null
@@ -0,0 +1,229 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * system-plugin-common
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gio/gio.h>
+
+#include "util.h"
+#include "dbus-common.h"
+#include "systemd.h"
+
+#define SYSTEMD_UNIT_OBJ_PATH_PREFIX    "/org/freedesktop/systemd1/unit/"
+#define SYSTEMD_UNIT_ESCAPE_CHAR        ".-"
+
+static char *get_systemd_unit_obj_path(const char* unit) {
+        char *path = NULL;
+        int i, j;
+        size_t p, k, prefix_len, unit_len = strlen(unit);
+
+        for (i=0, p=0; p<unit_len; i++) {
+                k = strcspn(unit+p, SYSTEMD_UNIT_ESCAPE_CHAR);
+                p += k+1;
+        }
+
+        prefix_len = strlen(SYSTEMD_UNIT_OBJ_PATH_PREFIX);
+        /* assume we try to get object path of foo-bar.service then
+         * the object path will be
+         * "/org/freedesktop/systemd1/unit/foo_2dbar_2eservice\n". In
+         * this case we can find two escape characters, so the total
+         * length will be:
+         * (PREFIX_length) + (unit_length - escape + 3*escape) + NULL */
+        path = new0(char,
+                    prefix_len
+                    + (unit_len - (i-1)) + ((i-1) * 3 * sizeof(char))
+                    + 1);
+        strncpy(path, SYSTEMD_UNIT_OBJ_PATH_PREFIX, prefix_len+1);
+
+        for (j=0, p=0; j < i; j++) {
+                k = strcspn(unit+p, SYSTEMD_UNIT_ESCAPE_CHAR);
+                strncpy(path+prefix_len, unit+p, k);
+                if (k < strlen(unit+p)) {
+                        sprintf(path+prefix_len+k, "_%x", *(unit+p+k) & 0xff);
+                        prefix_len += k+3;
+                        p += k+1;
+                }
+        }
+
+        return path;
+}
+
+static int systemd_get_property(GBusType type,
+                                const char *name,
+                                const char *path,
+                                const char *iface,
+                                const char *method,
+                                const char *interface,
+                                const char *property,
+                                GVariant **variant) {
+
+        GDBusConnection *connection;
+        GVariant *gvar;
+        GError *error;
+        GDBusProxy *proxy;
+
+#if (GLIB_MAJOR_VERSION <= 2 && GLIB_MINOR_VERSION < 36)
+        g_type_init ();
+#endif
+
+        error = NULL;
+        proxy = g_dbus_proxy_new_for_bus_sync(type ? G_BUS_TYPE_SYSTEM : G_BUS_TYPE_SESSION,
+                                              G_DBUS_PROXY_FLAGS_NONE,
+                                              NULL, /* GDBusInterfaceInfo */
+                                              name,
+                                              path,
+                                              iface,
+                                              NULL, /* GCancellable */
+                                              &error);
+
+        if (proxy == NULL) {
+                g_printerr("Error creating proxy: %s\n", error->message);
+                g_error_free(error);
+                return -1;
+        }
+
+        error = NULL;
+        gvar = g_dbus_proxy_call_sync(proxy,
+                                      method,
+                                      g_variant_new ("(ss)",
+                                                     interface,
+                                                     property),
+                                      G_DBUS_CALL_FLAGS_NONE,
+                                      -1,
+                                      NULL, /* GCancellable */
+                                      &error);
+
+        g_assert_no_error(error);
+        g_assert(gvar != NULL);
+        *variant = gvar;
+        g_clear_error (&error);
+        g_object_unref(proxy);
+
+        return 0;
+}
+
+int systemd_get_manager_property(const char *iface,
+                                 const char *property,
+                                 GVariant **variant) {
+
+        return systemd_get_property(G_BUS_TYPE_SYSTEM,
+                                    DBUS_SYSTEMD_DEST,
+                                    DBUS_SYSTEMD_ADDRESS,
+                                    DBUS_INTERFACE_DBUS_PROPERTIES,
+                                    "Get",
+                                    iface,
+                                    property,
+                                    variant);
+}
+
+int systemd_get_unit_property(const char *unit,
+                              const char *property,
+                              GVariant **variant) {
+
+        _cleanup_free_ char *systemd_unit_obj_path;
+
+        systemd_unit_obj_path = get_systemd_unit_obj_path(unit);
+
+        return systemd_get_property(G_BUS_TYPE_SYSTEM,
+                                    DBUS_SYSTEMD_DEST,
+                                    systemd_unit_obj_path,
+                                    DBUS_INTERFACE_DBUS_PROPERTIES,
+                                    "Get",
+                                    DBUS_INTERFACE_SYSTEMD_UNIT,
+                                    property,
+                                    variant);
+}
+
+int systemd_get_service_property(const char *unit,
+                                 const char *property,
+                                 GVariant **variant) {
+
+        _cleanup_free_ char *systemd_unit_obj_path;
+
+        systemd_unit_obj_path = get_systemd_unit_obj_path(unit);
+
+        return systemd_get_property(G_BUS_TYPE_SYSTEM,
+                                    DBUS_SYSTEMD_DEST,
+                                    systemd_unit_obj_path,
+                                    DBUS_INTERFACE_DBUS_PROPERTIES,
+                                    "Get",
+                                    DBUS_INTERFACE_SYSTEMD_SERVICE,
+                                    property,
+                                    variant);
+}
+
+typedef unsigned int uint;
+typedef long long int64;
+typedef unsigned long long uint64;
+
+#define g_variant_type_int32    G_VARIANT_TYPE_INT32
+#define g_variant_type_int64    G_VARIANT_TYPE_INT64
+#define g_variant_type_uint32   G_VARIANT_TYPE_UINT32
+#define g_variant_type_uint64   G_VARIANT_TYPE_UINT64
+#define g_variant_type_string   G_VARIANT_TYPE_STRING
+
+#define g_variant_get_function_int32(v)   g_variant_get_int32(v)
+#define g_variant_get_function_int64(v)   g_variant_get_int64(v)
+#define g_variant_get_function_uint32(v)  g_variant_get_uint32(v)
+#define g_variant_get_function_uint64(v)  g_variant_get_uint64(v)
+#define g_variant_get_function_string(v)  g_variant_dup_string(v, NULL)
+
+#define DEFINE_SYSTEMD_GET_PROPERTY(iface, type, value)                 \
+        int systemd_get_##iface##_property_as_##type(                   \
+                        const char* target,                             \
+                        const char* property,                           \
+                        value* result) {                                \
+                                                                        \
+                GVariant *var;                                          \
+                GVariant *inner;                                        \
+                int r;                                                  \
+                                                                        \
+                r = systemd_get_##iface##_property(target, property, &var); \
+                                                                        \
+                if (r < 0) {                                            \
+                        fprintf(stderr, "Failed to get property:\n  target: %s\n  property: %s\n", \
+                                target, property);                      \
+                        return r;                                       \
+                }                                                       \
+                                                                        \
+                g_assert(g_variant_is_of_type(var, G_VARIANT_TYPE("(v)"))); \
+                g_variant_get(var, "(v)", &inner);                      \
+                g_assert(g_variant_is_of_type(inner, g_variant_type_##type)); \
+                *result = g_variant_get_function_##type(inner);         \
+                g_variant_unref(var);                                   \
+                                                                        \
+                return 0;                                               \
+        }
+
+
+DEFINE_SYSTEMD_GET_PROPERTY(manager, int32, int)
+DEFINE_SYSTEMD_GET_PROPERTY(manager, uint32, uint)
+DEFINE_SYSTEMD_GET_PROPERTY(manager, int64, long long)
+DEFINE_SYSTEMD_GET_PROPERTY(manager, uint64, unsigned long long)
+DEFINE_SYSTEMD_GET_PROPERTY(manager, string, char*)
+DEFINE_SYSTEMD_GET_PROPERTY(unit, int32, int)
+DEFINE_SYSTEMD_GET_PROPERTY(unit, uint32, uint)
+DEFINE_SYSTEMD_GET_PROPERTY(unit, int64, long long)
+DEFINE_SYSTEMD_GET_PROPERTY(unit, uint64, unsigned long long)
+DEFINE_SYSTEMD_GET_PROPERTY(unit, string, char*)
+DEFINE_SYSTEMD_GET_PROPERTY(service, int32, int)
+DEFINE_SYSTEMD_GET_PROPERTY(service, uint32, uint)
+DEFINE_SYSTEMD_GET_PROPERTY(service, int64, long long)
+DEFINE_SYSTEMD_GET_PROPERTY(service, uint64, unsigned long long)
+DEFINE_SYSTEMD_GET_PROPERTY(service, string, char*)
diff --git a/src/shared/systemd.h b/src/shared/systemd.h
new file mode 100644 (file)
index 0000000..aa29e1c
--- /dev/null
@@ -0,0 +1,67 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * system-plugin-common
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * 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
+
+#include <dbus/dbus.h>
+#include <gio/gio.h>
+
+enum SystemdUnitType {
+        SYSTEMD_UNIT_SERVICE,
+        SYSTEMD_UNIT_SOCKET,
+        SYSTEMD_UNIT_DEVICE,
+        SYSTEMD_UNIT_MOUNT,
+        SYSTEMD_UNIT_AUTOMOUNT,
+        SYSTEMD_UNIT_SWAP,
+        SYSTEMD_UNIT_TARGET,
+        SYSTEMD_UNIT_PATH,
+        SYSTEMD_UNIT_TIMER,
+        SYSTEMD_UNIT_SNAPSHOT,
+        SYSTEMD_UNIT_SLICE,
+        SYSTEMD_UNIT_SCOPE,
+        _SYSTEMD_UNIT_TYPE_MAX,
+        _SYSTEMD_UNIT_TYPE_INVALID = -1
+};
+
+#define DBUS_SYSTEMD_DEST               "org.freedesktop.systemd1"
+#define DBUS_SYSTEMD_ADDRESS            "/org/freedesktop/systemd1"
+#define DBUS_INTERFACE_SYSTEMD_MANAGER  DBUS_SYSTEMD_DEST ".Manager"
+#define DBUS_INTERFACE_SYSTEMD_UNIT     DBUS_SYSTEMD_DEST ".Unit"
+#define DBUS_INTERFACE_SYSTEMD_SERVICE  DBUS_SYSTEMD_DEST ".Service"
+#define DBUS_INTERFACE_SYSTEMD_TARGET   DBUS_SYSTEMD_DEST ".Target"
+
+int systemd_get_unit_property(const char *unit, const char *property, GVariant **variant);
+int systemd_get_service_property(const char* unit, const char* property, GVariant **variant);
+
+int systemd_get_manager_property_as_int32(const char *iface, const char *property, int *result);
+int systemd_get_manager_property_as_uint32(const char *iface, const char *property, unsigned int *result);
+int systemd_get_manager_property_as_int64(const char *iface, const char *property, long long *result);
+int systemd_get_manager_property_as_uint64(const char *iface, const char *property, unsigned long long *result);
+int systemd_get_manager_property_as_string(const char *iface, const char *property, char **result);
+int systemd_get_unit_property_as_int32(const char *unit, const char *property, int *result);
+int systemd_get_unit_property_as_uint32(const char *unit, const char *property, unsigned int *result);
+int systemd_get_unit_property_as_int64(const char *unit, const char *property, long long *result);
+int systemd_get_unit_property_as_uint64(const char *unit, const char *property, unsigned long long *result);
+int systemd_get_unit_property_as_string(const char *unit, const char *property, char **result);
+int systemd_get_service_property_as_int32(const char *unit, const char *property, int *result);
+int systemd_get_service_property_as_uint32(const char *unit, const char *property, unsigned int *result);
+int systemd_get_service_property_as_int64(const char *unit, const char *property, long long *result);
+int systemd_get_service_property_as_uint64(const char *unit, const char *property, unsigned long long *result);
+int systemd_get_service_property_as_string(const char *unit, const char *property, char **result);
diff --git a/src/shared/util.c b/src/shared/util.c
new file mode 100644 (file)
index 0000000..2d98f1a
--- /dev/null
@@ -0,0 +1,382 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * system-plugin-common
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stddef.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+
+#include "fileio.h"
+#include "util.h"
+
+/* In old kernel, this symbol maybe NOT */
+#ifndef TASK_COMM_LEN
+#define TASK_COMM_LEN 16
+#endif
+
+bool streq_ptr(const char *a, const char *b) {
+
+        /* Like streq(), but tries to make sense of NULL pointers */
+
+        if (a && b)
+                return streq(a, b);
+
+        if (!a && !b)
+                return true;
+
+        return false;
+}
+
+char *truncate_nl(char *s) {
+        assert(s);
+
+        s[strcspn(s, NEWLINE)] = 0;
+
+        return s;
+}
+
+char *strnappend(const char *s, const char *suffix, size_t b) {
+        size_t a;
+        char *r;
+
+        if (!s && !suffix)
+                return strdup("");
+
+        if (!s)
+                return strndup(suffix, b);
+
+        if (!suffix)
+                return strdup(s);
+
+        assert(s);
+        assert(suffix);
+
+        a = strlen(s);
+        if (b > ((size_t) -1) - a)
+                return NULL;
+
+        r = new(char, a+b+1);
+        if (!r)
+                return NULL;
+
+        memcpy(r, s, a);
+        memcpy(r+a, suffix, b);
+        r[a+b] = 0;
+
+        return r;
+}
+
+char *strappend(const char *s, const char *suffix) {
+        return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
+}
+
+char *strstrip(char *s) {
+        char *e;
+
+        /* Drops trailing whitespace. Modifies the string in
+         * place. Returns pointer to first non-space character */
+
+        s += strspn(s, WHITESPACE);
+
+        for (e = strchr(s, 0); e > s; e --)
+                if (!strchr(WHITESPACE, e[-1]))
+                        break;
+
+        *e = 0;
+
+        return s;
+}
+
+char *file_in_same_dir(const char *path, const char *filename) {
+        char *e, *r;
+        size_t k;
+
+        assert(path);
+        assert(filename);
+
+        /* This removes the last component of path and appends
+         * filename, unless the latter is absolute anyway or the
+         * former isn't */
+
+        if (path_is_absolute(filename))
+                return strdup(filename);
+
+        if (!(e = strrchr(path, '/')))
+                return strdup(filename);
+
+        k = strlen(filename);
+        if (!(r = new(char, e-path+1+k+1)))
+                return NULL;
+
+        memcpy(r, path, e-path+1);
+        memcpy(r+(e-path)+1, filename, k+1);
+
+        return r;
+}
+
+bool nulstr_contains(const char*nulstr, const char *needle) {
+        const char *i;
+
+        if (!nulstr)
+                return false;
+
+        NULSTR_FOREACH(i, nulstr)
+                if (streq(i, needle))
+                        return true;
+
+        return false;
+}
+
+bool path_is_absolute(const char *p) {
+        return p[0] == '/';
+}
+
+char *path_kill_slashes(char *path) {
+        char *f, *t;
+        bool slash = false;
+
+        /* Removes redundant inner and trailing slashes. Modifies the
+         * passed string in-place.
+         *
+         * ///foo///bar/ becomes /foo/bar
+         */
+
+        for (f = path, t = path; *f; f++) {
+
+                if (*f == '/') {
+                        slash = true;
+                        continue;
+                }
+
+                if (slash) {
+                        slash = false;
+                        *(t++) = '/';
+                }
+
+                *(t++) = *f;
+        }
+
+        /* Special rule, if we are talking of the root directory, a
+           trailing slash is good */
+
+        if (t == path && slash)
+                *(t++) = '/';
+
+        *t = 0;
+        return path;
+}
+
+char* endswith(const char *s, const char *postfix) {
+        size_t sl, pl;
+
+        assert(s);
+        assert(postfix);
+
+        sl = strlen(s);
+        pl = strlen(postfix);
+
+        if (pl == 0)
+                return (char*) s + sl;
+
+        if (sl < pl)
+                return NULL;
+
+        if (memcmp(s + sl - pl, postfix, pl) != 0)
+                return NULL;
+
+        return (char*) s + sl - pl;
+}
+
+int parse_boolean(const char *v) {
+        assert(v);
+
+        if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || strcaseeq(v, "on"))
+                return 1;
+        else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || strcaseeq(v, "off"))
+                return 0;
+
+        return -EINVAL;
+}
+
+/* Split a string into words. */
+char *split(const char *c, size_t *l, const char *separator, char **state) {
+        char *current;
+
+        current = *state ? *state : (char*) c;
+
+        if (!*current || *c == 0)
+                return NULL;
+
+        current += strspn(current, separator);
+        *l = strcspn(current, separator);
+        *state = current+*l;
+
+        return (char*) current;
+}
+
+bool is_number(const char *s, int l) {
+        int i;
+
+        for (i = 0; i < l; i++)
+                if (!isdigit(s[i]))
+                        return false;
+
+        return true;
+}
+
+int pid_of(const char *pname) {
+        _cleanup_closedir_ DIR *dir = NULL;
+        struct dirent *de;
+        int r;
+
+        dir = opendir("/proc");
+        if (!dir) {
+                fprintf(stderr, "Failed to open dir: %s", "/proc");
+                return -errno;
+        }
+
+        FOREACH_DIRENT(de, dir, return -errno) {
+                _cleanup_free_ char *path = NULL;
+                _cleanup_free_ char *comm = NULL;
+
+                if (de->d_type != DT_DIR)
+                        continue;
+
+                if (!is_number(de->d_name, strlen(de->d_name)))
+                        continue;
+
+                r = asprintf(&path, "/proc/%s/comm", de->d_name);
+                if (r < 0)
+                        return -ENOMEM;
+
+                r = read_one_line_file(path, &comm);
+                if (r < 0)
+                        continue;
+
+                if (strneq(pname, comm, TASK_COMM_LEN-1))
+                        return atoi(de->d_name);
+        }
+
+        return 0;
+}
+
+int do_copy(const char *src, const char *dst, const char *option) {
+        pid_t pid;
+        int status;
+
+        pid = fork();
+        if (pid == 0) { /* child */
+                execl("/bin/cp",
+                      "/bin/cp", src,  dst, option, (char *)0);
+                _exit(1);
+        }
+        else if (pid < 0)
+                return -errno;
+        /* TODO */
+        /* Child wait status should be checked. */
+        wait(&status);
+        return 0;
+}
+
+int do_mkdir_one(const char *path, mode_t mode) {
+        int r;
+
+        assert(path);
+
+        r = mkdir(path, mode);
+        if (r < 0) {
+                fprintf(stderr, "cannot create directory '%s': %m\n", path);
+                return r;
+        }
+
+        return 0;
+}
+
+int do_mkdir(const char *path, mode_t mode) {
+        size_t s, l;
+        int p;
+        int r;
+
+        assert(path);
+
+        l = strlen(path);
+
+        for (p = 0, s = 0; p < l; p += s+1) {
+                _cleanup_free_ char *d = new0(char, p+s+1);
+
+                s = strcspn(path+p, "/");
+                if (!s)
+                        continue;
+
+                r = snprintf(d, p+s+1, "%s", path);
+                if (r < 0)
+                        return r;
+
+                r = access(d, W_OK);
+                if (r == 0)
+                        continue;
+                else if (r < 0 && errno != ENOENT) {
+                        fprintf(stderr,
+                                "cannot create directory '%s': %m\n", d);
+                        return r;
+                }
+
+                r = do_mkdir_one(d, mode);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+int rmdir_recursive(const char *path) {
+        _cleanup_closedir_ DIR *d = NULL;
+        struct dirent *de;
+        int r;
+
+        assert(path);
+
+        d = opendir(path);
+        if (!d)
+                return -errno;
+
+        FOREACH_DIRENT(de, d, return -errno) {
+                _cleanup_free_ char *p = NULL;
+
+                r = asprintf(&p, "%s/%s", path, de->d_name);
+                if (r < 0)
+                        return -ENOMEM;
+
+                if (de->d_type == DT_DIR) {
+                        r = rmdir_recursive(p);
+                        if (r < 0)
+                                return r;
+                } else {
+                        r = unlink(p);
+                        if (r < 0)
+                                return r;
+                }
+        }
+
+        return rmdir(path);
+}
diff --git a/src/shared/util.h b/src/shared/util.h
new file mode 100644 (file)
index 0000000..4340874
--- /dev/null
@@ -0,0 +1,109 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * system-plugin-common
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * 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
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <dirent.h>
+
+#include "macro.h"
+
+#define WHITESPACE " \t\n\r"
+#define NEWLINE "\n\r"
+#define QUOTES "\"\'"
+#define COMMENTS "#;"
+
+static inline void freep(void *p) {
+        free(*(void**) p);
+}
+
+static inline void fclosep(FILE **f) {
+        if (*f)
+                fclose(*f);
+}
+
+static inline void closedirp(DIR **d) {
+        if (*d)
+                closedir(*d);
+}
+
+static inline const char *startswith(const char *s, const char *prefix) {
+        if (strncmp(s, prefix, strlen(prefix)) == 0)
+                return s + strlen(prefix);
+        return NULL;
+}
+
+#define _cleanup_free_ _cleanup_(freep)
+#define _cleanup_fclose_ _cleanup_(fclosep)
+#define _cleanup_closedir_ _cleanup_(closedirp)
+
+#define streq(a,b) (strcmp((a),(b)) == 0)
+#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
+#define strcaseeq(a,b) (strcasecmp((a),(b)) == 0)
+#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0)
+
+#define new(t, n) ((t*) malloc(sizeof(t) * (n)))
+#define new0(t, n) ((t*) calloc((n), sizeof(t)))
+#define malloc0(n) (calloc((n), 1))
+
+#define NULSTR_FOREACH(i, l)                                    \
+        for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
+
+bool streq_ptr(const char *a, const char *b) _pure_;
+int parse_boolean(const char *v) _pure_;
+char *truncate_nl(char *s);
+char *strnappend(const char *s, const char *suffix, size_t b);
+char *strappend(const char *s, const char *suffix);
+char *strstrip(char *s);
+char *file_in_same_dir(const char *path, const char *filename);
+bool nulstr_contains(const char*nulstr, const char *needle);
+bool path_is_absolute(const char *p);
+char *path_kill_slashes(char *path);
+char* endswith(const char *s, const char *postfix);
+
+char *split(const char *c, size_t *l, const char *separator, char **state);
+
+#define FOREACH_WORD(word, length, s, state)                            \
+        for ((state) = NULL, (word) = split((s), &(length), WHITESPACE, &(state)); (word); (word) = split((s), &(length), WHITESPACE, &(state)))
+
+#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state)       \
+        for ((state) = NULL, (word) = split((s), &(length), (separator), &(state)); (word); (word) = split((s), &(length), (separator), &(state)))
+
+#define FOREACH_DIRENT(de, d, on_error)                                 \
+        for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d))   \
+                if (!de) {                                              \
+                        if (errno > 0) {                                \
+                                on_error;                               \
+                        }                                               \
+                        break;                                          \
+                } else if (streq(de->d_name, ".") ||                    \
+                           streq(de->d_name, ".."))                     \
+                        continue;                                       \
+                else
+
+bool is_number(const char *s, int l);
+int pid_of(const char *pname);
+int do_copy(const char *src, const char *dst, const char *option);
+int do_mkdir_one(const char *path, mode_t mode);
+int do_mkdir(const char *path, mode_t mode);
+int rmdir_recursive(const char *path);
diff --git a/sysctl.d/50-tizen-default.conf.in b/sysctl.d/50-tizen-default.conf.in
new file mode 100644 (file)
index 0000000..4225340
--- /dev/null
@@ -0,0 +1,12 @@
+# See sysctl.d(5) and core(5) for for details.
+
+# This specifies an upper limit on the number of inotify instances
+# that can be created per real user ID.
+fs.inotify.max_user_instances=1024
+
+# In hundredths of a second, this is how often pdflush wakes up to
+# write data to disk.
+vm.dirty_writeback_centisecs=@DIRTY_WRITEBACK_CENTISECS@
+
+# config overcommit handling mode
+vm.overcommit_memory = 1
diff --git a/units/cleanup-storage.service b/units/cleanup-storage.service
new file mode 100644 (file)
index 0000000..426a02d
--- /dev/null
@@ -0,0 +1,10 @@
+[Unit]
+Description=Cleanup Storage
+DefaultDependencies=no
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/cleanup-storage.sh
+
+[Install]
+WantedBy=basic.target
diff --git a/units/cleanup-storage.timer b/units/cleanup-storage.timer
new file mode 100644 (file)
index 0000000..c94c753
--- /dev/null
@@ -0,0 +1,5 @@
+[Unit]
+Description=Timer for cleanup-storage
+
+[Timer]
+OnCalendar=*-*-* 05:00:00
diff --git a/units/ghost.service b/units/ghost.service
new file mode 100644 (file)
index 0000000..af5f376
--- /dev/null
@@ -0,0 +1,13 @@
+[Unit]
+Description=ghost process
+DefaultDependencies=no
+Requires=dbus.socket
+After=dbus.socket
+
+[Service]
+ExecStart=/usr/bin/ghost
+StandardOutput=journal+console
+StandardError=inherit
+
+[Install]
+WantedBy=multi-user.target
diff --git a/units/init-conf.service b/units/init-conf.service
new file mode 100644 (file)
index 0000000..b62d0d6
--- /dev/null
@@ -0,0 +1,14 @@
+[Unit]
+Description=Run init.%H.conf
+DefaultDependencies=no
+After=local-fs.target
+Conflicts=shutdown.target
+Before=sysinit.target shutdown.target
+ConditionFileNotEmpty=/etc/init.%H.conf
+
+[Service]
+Type=oneshot
+ExecStart=/bin/bash -c '/etc/init.%H.conf'
+
+[Install]
+WantedBy=sysinit.target
diff --git a/units/tizen-boot.target b/units/tizen-boot.target
new file mode 100644 (file)
index 0000000..1533be5
--- /dev/null
@@ -0,0 +1,6 @@
+[Unit]
+Description=Tizen Boot
+Requires=basic.target
+Conflicts=rescue.service rescue.target
+After=basic.target rescue.service rescue.target
+Before=multi-user.target
index d92f210..a0cfe33 100644 (file)
@@ -5,3 +5,5 @@ Requires=opt-usr.mount
 [Service]
 Type=oneshot
 ExecStart=/usr/bin/tizen-fstrim-on-charge.sh /opt/usr
+StandardOutput=journal
+StandardError=inherit
diff --git a/units/tizen-journal-flush.service b/units/tizen-journal-flush.service
new file mode 100644 (file)
index 0000000..9a2d2ee
--- /dev/null
@@ -0,0 +1,11 @@
+#  This file is copied from systemd to modify.
+
+[Unit]
+Description=Trigger Flushing of Journal to Persistent Storage
+Documentation=man:systemd-journald.service(8) man:journald.conf(5)
+Requires=systemd-journald.service
+After=systemd-journald.service default.target
+
+[Service]
+ExecStart=/usr/bin/systemctl kill --kill-who=main --signal=SIGUSR1 systemd-journald.service
+Type=oneshot
index fd59c5f..9d4aeaa 100644 (file)
@@ -1,8 +1,14 @@
 [Unit]
-Description=Stop Collecting Read-Ahead Data
+Description=Stop Read-Ahead Data Collection
+DefaultDependencies=no
+Conflicts=shutdown.target
 After=tizen-readahead-collect.service boot-animation.service
-Before=tizen-system.target
+Before=shutdown.target tizen-system.target
+ConditionVirtualization=no
 
 [Service]
 Type=oneshot
-ExecStart=/usr/bin/systemctl stop tizen-readahead-collect.service
+ExecStart=/usr/bin/systemd-notify --readahead=done
+
+[Install]
+Also=tizen-readahead-collect.service
index bec9d73..8b0c5c3 100644 (file)
@@ -1,15 +1,18 @@
 [Unit]
 Description=Collect Read-Ahead Data
 DefaultDependencies=no
+Wants=tizen-readahead-collect-stop.service
 Conflicts=shutdown.target
-After=smack.service smack_pre_labeling_priv.service tizen-readahead-replay.service
+After=smack.service smack-default-labeling.service tizen-readahead-replay.service
 Before=sysinit.target shutdown.target
-Wants=tizen-readahead-collect-stop.service
+ConditionPathExists=!/run/systemd/readahead/cancel
+ConditionPathExists=!/run/systemd/readahead/done
 ConditionPathExists=!@READAHEAD_DIR@/.readahead
+ConditionVirtualization=no
 
 [Service]
 Type=notify
-ExecStart=/usr/lib/systemd/systemd-readahead collect --savedir=@READAHEAD_DIR@
+ExecStart=@rootlibexecdir@/systemd-readahead collect --savedir=@READAHEAD_DIR@
 RemainAfterExit=yes
 StandardOutput=null
 
index fa6e9f4..22f00dd 100644 (file)
@@ -2,15 +2,18 @@
 Description=Replay Read-Ahead Data
 DefaultDependencies=no
 Conflicts=shutdown.target
-After=smack.service smack_pre_labeling_priv.service
+After=smack.service smack-default-labeling.service
 Before=sysinit.target shutdown.target
+ConditionPathExists=!/run/systemd/readahead/noreplay
 ConditionPathExists=@READAHEAD_DIR@/.readahead
+ConditionVirtualization=no
 
 [Service]
 Type=notify
-ExecStart=/usr/lib/systemd/systemd-readahead replay --savedir=@READAHEAD_DIR@
+ExecStart=@rootlibexecdir@/systemd-readahead replay --savedir=@READAHEAD_DIR@
 RemainAfterExit=yes
 StandardOutput=null
+OOMScoreAdjust=1000
 
 [Install]
-WantedBy=multi-user.target
+WantedBy=graphical.target
diff --git a/units/tizen-runtime.target b/units/tizen-runtime.target
new file mode 100644 (file)
index 0000000..b1bc216
--- /dev/null
@@ -0,0 +1,6 @@
+[Unit]
+Description=Tizen Runtime
+Requires=basic.target tizen-boot.target tizen-system.target
+Conflicts=rescue.service rescue.target
+After=basic.target tizen-boot.target tizen-system.target rescue.service rescue.target
+Before=multi-user.target
diff --git a/units/tizen-system.target b/units/tizen-system.target
new file mode 100644 (file)
index 0000000..4240819
--- /dev/null
@@ -0,0 +1,6 @@
+[Unit]
+Description=Tizen System
+Requires=basic.target tizen-boot.target
+Conflicts=rescue.service rescue.target
+After=basic.target tizen-boot.target rescue.service rescue.target
+Before=multi-user.target
index d8c182f..e3f260b 100644 (file)
@@ -6,6 +6,7 @@ Before=tizen-boot.target
 [Service]
 Type=oneshot
 ExecStart=/bin/sh -c 'while [ ! -e /tmp/.wm_ready ]; do sleep 0.1 ; done'
+TimeoutSec=10s
 
 [Install]
 WantedBy=tizen-boot.target