--- /dev/null
+*.[ch] whitespace=tab-in-indent,trailing-space
--- /dev/null
+*.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
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@
engbindir=/opt/usr/devel/$(rootbindir)
endif
+if MOBILE
+noinst_LTLIBRARIES =
+noinst_DATA =
+sysctl_DATA =
+endif
+
bin_SCRIPTS =
rc_SCRIPTS =
SCRIPT_IN_FILES =
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 =
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)
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)
# 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 += \
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
tizen-readahead-collect.service \
tizen-init-done.service
-TIZEN_SYSTEM_TARGET_WANTS += \
- check-mount.service
-
MULTI_USER_TARGET_WANTS += \
tizen-readahead-replay.service
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 += \
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)|' \
'|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 $@) && \
$(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 < $< > $@
--- /dev/null
+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".
--- /dev/null
+#!/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 $?
opt-usr-fsck.service
osp-tmpdir-setup.service
pkgmgr_recovery.service
-power_qcom_init.service
pulseaudio.service
qmuxd.service
qseecom_ready.service
tee-qsee.service
telephony-daemon.service
time.service
-trm.service
wifi-module-check.service
wm_ready.service
wrt-security-daemon.service
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
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],
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])
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]),
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]),
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}
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}
])
###########################
# 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
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
%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
%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}
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
%{_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
%{_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
%{_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
--- /dev/null
+# 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"
# 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
;;
--- /dev/null
+#!/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
#!/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
#!/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
--- /dev/null
+/*-*- 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;
+}
--- /dev/null
+[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')
--- /dev/null
+/*-*- 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,
+ <ype,
+ &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;
+}
--- /dev/null
+/*-*- 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);
--- /dev/null
+/*-*- 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"
--- /dev/null
+/*-*- 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);
+}
--- /dev/null
+/*-*- 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);
--- /dev/null
+/*-*- 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)))
--- /dev/null
+/*-*- 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*)
--- /dev/null
+/*-*- 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);
--- /dev/null
+/*-*- 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);
+}
--- /dev/null
+/*-*- 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);
--- /dev/null
+# 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
--- /dev/null
+[Unit]
+Description=Cleanup Storage
+DefaultDependencies=no
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/cleanup-storage.sh
+
+[Install]
+WantedBy=basic.target
--- /dev/null
+[Unit]
+Description=Timer for cleanup-storage
+
+[Timer]
+OnCalendar=*-*-* 05:00:00
--- /dev/null
+[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
--- /dev/null
+[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
--- /dev/null
+[Unit]
+Description=Tizen Boot
+Requires=basic.target
+Conflicts=rescue.service rescue.target
+After=basic.target rescue.service rescue.target
+Before=multi-user.target
[Service]
Type=oneshot
ExecStart=/usr/bin/tizen-fstrim-on-charge.sh /opt/usr
+StandardOutput=journal
+StandardError=inherit
--- /dev/null
+# 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
[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
[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
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
--- /dev/null
+[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
--- /dev/null
+[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
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'while [ ! -e /tmp/.wm_ready ]; do sleep 0.1 ; done'
+TimeoutSec=10s
[Install]
WantedBy=tizen-boot.target