summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjk7744.park <jk7744.park@samsung.com>2015-09-08 21:30:39 +0900
committerjk7744.park <jk7744.park@samsung.com>2015-09-08 21:30:39 +0900
commitf66f61d6d5c9f9928f140ebfbda80284d1331529 (patch)
treedda135629da91b07d36b25d54258964c185144c7
parent7253ef7586e0cc619b996566965a185f0c2a7cbc (diff)
downloadsystem-plugin-common-f66f61d6d5c9f9928f140ebfbda80284d1331529.tar.gz
system-plugin-common-f66f61d6d5c9f9928f140ebfbda80284d1331529.tar.bz2
system-plugin-common-f66f61d6d5c9f9928f140ebfbda80284d1331529.zip
-rw-r--r--.gitattributes1
-rw-r--r--.gitignore25
-rw-r--r--AUTHORS1
-rw-r--r--ChangeLog0
-rw-r--r--LICENSE202
-rw-r--r--Makefile.am384
-rw-r--r--NEWS0
-rw-r--r--TODO16
-rwxr-xr-xautogen.sh21
-rw-r--r--conf/systemd/ignore-units38
-rw-r--r--configure.ac188
-rw-r--r--packaging/system-plugin-common.manifest12
-rw-r--r--packaging/system-plugin-common.spec179
-rw-r--r--rules/51-tizen-udev-default.rules22
-rw-r--r--scripts/change-booting-mode.sh112
-rw-r--r--scripts/cleanup-storage.sh92
-rw-r--r--scripts/tizen-boot.sh.in112
-rw-r--r--scripts/tizen-fstrim-on-charge.sh21
-rw-r--r--src/ghost/ghost.c656
-rw-r--r--src/ghost/ghost.conf.m410
-rw-r--r--src/shared/conf-parser.c243
-rw-r--r--src/shared/conf-parser.h62
-rw-r--r--src/shared/dbus-common.h27
-rw-r--r--src/shared/fileio.c90
-rw-r--r--src/shared/fileio.h28
-rw-r--r--src/shared/macro.h24
-rw-r--r--src/shared/systemd.c229
-rw-r--r--src/shared/systemd.h67
-rw-r--r--src/shared/util.c382
-rw-r--r--src/shared/util.h109
-rw-r--r--sysctl.d/50-tizen-default.conf.in12
-rw-r--r--units/check-mount.service14
-rw-r--r--units/cleanup-storage.service10
-rw-r--r--units/cleanup-storage.timer5
-rw-r--r--units/ghost.service13
-rw-r--r--units/init-conf.service14
-rw-r--r--units/systemd-udevd-kill.service8
-rw-r--r--units/systemd-udevd-kill.timer9
-rw-r--r--units/tizen-boot.target6
-rw-r--r--units/tizen-fstrim-user.service9
-rw-r--r--units/tizen-fstrim-user.timer.m48
-rw-r--r--units/tizen-generate-env.service12
-rw-r--r--units/tizen-init-check.service.in11
-rw-r--r--units/tizen-init-done.service.in11
-rw-r--r--units/tizen-init.target5
-rw-r--r--units/tizen-initial-boot-done.service.in11
-rw-r--r--units/tizen-journal-flush.service11
-rw-r--r--units/tizen-readahead-collect-stop.service14
-rw-r--r--units/tizen-readahead-collect.service.in20
-rw-r--r--units/tizen-readahead-replay.service.in19
-rw-r--r--units/tizen-runtime.target6
-rw-r--r--units/tizen-system.target6
-rw-r--r--units/wm_ready.service12
53 files changed, 3599 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1841508
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.[ch] whitespace=tab-in-indent,trailing-space
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7385704
--- /dev/null
+++ b/.gitignore
@@ -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
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..be9d01b
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+WaLyong Cho <walyong.cho@samsung.com>
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..cb7c5bc
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,384 @@
+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
+
+SUBDIRS = .
+
+# legacy rc script dir
+rcdir=$(sysconfdir)/rc.d
+
+# Inherit from systemd
+systemdsysconfdir=$(sysconfdir)/systemd
+systemconfigunitdir=$(systemdsysconfdir)/system
+userconfigunitdir=$(systemdsysconfdir)/user
+systemdignoreunitdir=$(systemdsysconfdir)/default-extra-dependencies
+systemunitdir=$(rootprefix)/lib/systemd/system
+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@
+rootbindir=$(rootprefix)/bin
+rootlibexecdir=$(rootprefix)/lib/systemd
+
+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 =
+sysconf_DATA =
+systemdsysconf_DATA =
+systemdignoreunit_DATA =
+systemconfigunit_DATA =
+systemunit_DATA =
+udevrules_DATA =
+
+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 =
+
+SHUTDOWN_TARGET_WANTS =
+LOCAL_FS_TARGET_WANTS =
+BASIC_TARGET_WANTS =
+SYSINIT_TARGET_WANTS =
+SOCKETS_TARGET_WANTS =
+TIMERS_TARGET_WANTS =
+TIZEN_INIT_TARGET_WANTS =
+TIZEN_BOOT_TARGET_WANTS =
+TIZEN_SYSTEM_TARGET_WANTS =
+TIZEN_RUNTIME_TARGET_WANTS =
+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)
+ where=$(systemunitdir) && what="$(BASIC_TARGET_WANTS)" && wants=basic.target && $(add-wants)
+ where=$(systemunitdir) && what="$(MULTI_USER_TARGET_WANTS)" && wants=multi-user.target && $(add-wants)
+ where=$(systemunitdir) && what="$(SYSINIT_TARGET_WANTS)" && wants=sysinit.target && $(add-wants)
+ where=$(systemunitdir) && what="$(SOCKETS_TARGET_WANTS)" && wants=sockets.target && $(add-wants)
+ where=$(systemunitdir) && what="$(TIMERS_TARGET_WANTS)" && wants=timers.target && $(add-wants)
+ where=$(systemunitdir) && what="$(SLICES_TARGET_WANTS)" && wants=slices.target && $(add-wants)
+ where=$(systemunitdir) && what="$(TIZEN_INIT_TARGET_WANTS)" && wants=tizen-init.target && $(add-wants)
+ where=$(systemunitdir) && what="$(TIZEN_BOOT_TARGET_WANTS)" && wants=tizen-boot.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)
+
+define add-wants
+[ -z "$$what" -o -z "$$where" ] || ( \
+ dir=$(DESTDIR)$$where/$$wants.wants && \
+ $(MKDIR_P) -m 0755 $$dir && \
+ cd $$dir && \
+ rm -f $$what && \
+ for i in $$what; do $(LN_S) ../$$i . || exit $$? ; done )
+endef
+
+INSTALL_EXEC_HOOKS += \
+ install-target-wants-hook
+
+# ------------------------------------------------------------------------------
+# AM_V_M4 = $(AM_V_M4_$(V))
+# AM_V_M4_ = $(AM_V_M4_$(AM_DEFAULT_VERBOSITY))
+# AM_V_M4_0 = @echo " M4 " $@;
+#
+# AM_V_XSLT = $(AM_V_XSLT_$(V))
+# AM_V_XSLT_ = $(AM_V_XSLT_$(AM_DEFAULT_VERBOSITY))
+# AM_V_XSLT_0 = @echo " XSLT " $@;
+#
+# AM_V_GPERF = $(AM_V_GPERF_$(V))
+# AM_V_GPERF_ = $(AM_V_GPERF_$(AM_DEFAULT_VERBOSITY))
+# AM_V_GPERF_0 = @echo " GPERF " $@;
+#
+# AM_V_LN = $(AM_V_LN_$(V))
+# AM_V_LN_ = $(AM_V_LN_$(AM_DEFAULT_VERBOSITY))
+# 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-fstrim-on-charge.sh
+
+systemunit_DATA += \
+ units/check-mount.service \
+ units/tizen-generate-env.service \
+ units/tizen-readahead-collect.service \
+ units/tizen-readahead-collect-stop.service \
+ units/tizen-readahead-replay.service \
+ units/tizen-fstrim-user.service \
+ units/tizen-fstrim-user.timer \
+ units/tizen-init.target \
+ units/tizen-init-check.service \
+ units/tizen-initial-boot-done.service \
+ units/tizen-init-done.service
+
+BASIC_TARGET_WANTS += \
+ tizen-generate-env.service \
+ tizen-init-check.service
+
+TIZEN_INIT_TARGET_WANTS += \
+ tizen-readahead-collect.service \
+ tizen-init-done.service
+
+MULTI_USER_TARGET_WANTS += \
+ tizen-readahead-replay.service
+
+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 += \
+ units/wm_ready.service
+
+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)|' \
+ '|rootbindir=$(rootbindir)|' \
+ '|bindir=$(bindir)|' \
+ '|SYSTEMCTL=$(rootbindir)/systemctl|' \
+ '|SYSTEMD_NOTIFY=$(rootbindir)/systemd-notify|' \
+ '|systemdsysconfdir=$(systemdsysconfdir)|' \
+ '|SYSTEM_CONFIG_UNIT_PATH=$(systemdsysconfdir)/system|' \
+ '|USER_CONFIG_UNIT_PATH=$(systemdsysconfdir)/user|' \
+ '|pkgdatadir=$(pkgdatadir)|' \
+ '|systemunitdir=$(systemunitdir)|' \
+ '|userunitdir=$(userunitdir)|' \
+ '|systempresetdir=$(systempresetdir)|' \
+ '|userpresetdir=$(userpresetdir)|' \
+ '|udevhwdbdir=$(udevhwdbdir)|' \
+ '|udevrulesdir=$(udevrulesdir)|' \
+ '|catalogdir=$(catalogdir)|' \
+ '|tmpfilesdir=$(tmpfilesdir)|' \
+ '|sysctldir=$(sysctldir)|' \
+ '|PACKAGE_VERSION=$(PACKAGE_VERSION)|' \
+ '|PACKAGE_NAME=$(PACKAGE_NAME)|' \
+ '|PACKAGE_URL=$(PACKAGE_URL)|' \
+ '|RANDOM_SEED=$(localstatedir)/lib/random-seed|' \
+ '|prefix=$(prefix)|' \
+ '|exec_prefix=$(exec_prefix)|' \
+ '|libdir=$(libdir)|' \
+ '|includedir=$(includedir)|' \
+ '|VERSION=$(VERSION)|' \
+ '|rootprefix=$(rootprefix)|' \
+ '|udevlibexecdir=$(udevlibexecdir)|' \
+ '|SUSHELL=$(SUSHELL)|' \
+ '|DEBUGTTY=$(DEBUGTTY)|' \
+ '|KILL=$(KILL)|' \
+ '|KMOD=$(KMOD)|' \
+ '|MKDIR_P=$(MKDIR_P)|' \
+ '|QUOTAON=$(QUOTAON)|' \
+ '|QUOTACHECK=$(QUOTACHECK)|' \
+ '|SYSTEM_SYSVINIT_PATH=$(sysvinitdir)|' \
+ '|VARLOGDIR=$(varlogdir)|' \
+ '|RC_LOCAL_SCRIPT_PATH_START=$(RC_LOCAL_SCRIPT_PATH_START)|' \
+ '|RC_LOCAL_SCRIPT_PATH_STOP=$(RC_LOCAL_SCRIPT_PATH_STOP)|' \
+ '|PYTHON=$(PYTHON)|' \
+ '|PYTHON_BINARY=$(PYTHON_BINARY)|' \
+ '|INITAILBOOT_DONE=$(INITAILBOOT_DONE)|' \
+ '|INITIALIZE_DONE=$(INITIALIZE_DONE)|' \
+ '|READAHEAD_DIR=$(READAHEAD_DIR)|' \
+ '|DIRTY_WRITEBACK_CENTISECS=$(DIRTY_WRITEBACK_CENTISECS)|'
+
+SED_PROCESS = \
+ $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
+ $(SED) $(subst '|,-e 's|@,$(subst =,\@|,$(subst |',|g',$(substitutions)))) \
+ < $< > $@
+
+units/%: units/%.in Makefile
+ $(SED_PROCESS)
+
+%.rules: %.rules.in Makefile
+ $(SED_PROCESS)
+
+%.sh: %.sh.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 < $< > $@
+
+install-exec-hook: $(INSTALL_EXEC_HOOKS)
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/TODO b/TODO
new file mode 100644
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
index 0000000..968bc8e
--- /dev/null
+++ b/autogen.sh
@@ -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 $?
diff --git a/conf/systemd/ignore-units b/conf/systemd/ignore-units
new file mode 100644
index 0000000..95062a1
--- /dev/null
+++ b/conf/systemd/ignore-units
@@ -0,0 +1,38 @@
+ac.service
+alarm-server.service
+boot-osp.service
+check-mount.service
+crash-daemon.service
+csc-starter.service
+dbus.service
+factory-pretest.service
+factory-reset.service
+immvibed.service
+indicator.service
+irsc_util.service
+launchpad-preload.service
+messagebus.service
+ode-server.service
+opt-usr-fsck.service
+osp-tmpdir-setup.service
+pkgmgr_recovery.service
+pulseaudio.service
+qmuxd.service
+qseecom_ready.service
+recovery-update.service
+reset-verify.service
+rmt_storage.service
+samsung-secure-storage.service
+secure-storage.service
+security-server.service
+slp-pkgmgr.service
+smack-rules.service
+sound-server.service
+starter.service
+system-server.service
+tee-qsee.service
+telephony-daemon.service
+time.service
+wifi-module-check.service
+wm_ready.service
+wrt-security-daemon.service
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..cf97dd4
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,188 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+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
+AC_PROG_SED
+AC_PROG_GREP
+AC_PROG_AWK
+#AC_PROG_INSTALL
+
+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],
+ AS_HELP_STRING([--with-rootprefix=DIR],
+ [rootfs directory prefix for config files and kernel modules]),
+ [], [with_rootprefix=${ac_default_prefix}])
+AC_SUBST([rootprefix], [$with_rootprefix])
+
+# ------------------------------------------------------------------------------
+AC_ARG_ENABLE([engmode],
+ 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=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_ARG_WITH(initial-boot,
+ AS_HELP_STRING([--with-initialbootdone=PATH],
+ [tizen system initial boot done]),
+ [INITAILBOOT_DONE="$withval"],
+ [INITAILBOOT_DONE="/opt/etc/.initialboot_done"])
+AC_SUBST(INITAILBOOT_DONE)
+
+AC_ARG_WITH(need-initialized,
+ AS_HELP_STRING([--with-initializedone=PATH],
+ [tizen system need initialized done]),
+ [INITIALIZE_DONE="$withval"],
+ [INITIALIZE_DONE="/opt/etc/.initialize_done"])
+AC_SUBST(INITIALIZE_DONE)
+
+# ------------------------------------------------------------------------------
+AC_ARG_WITH(tizen-readahead,
+ AS_HELP_STRING([--with-tizenreadaheaddir=PATH],
+ [tizen readahead dir]),
+ [READAHEAD_DIR="$withval"],
+ [READAHEAD_DIR="/opt/etc"])
+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]),
+ [case "${enableval}" in
+ yes) enable_udevd_killer=yes ;;
+ no) enable_udevd_killer=no ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-udevd-killer) ;;
+ esac],
+ enable_udevd_killer=no)
+AC_SUBST(WITH_UDEVD_KILLER)
+AM_CONDITIONAL([WITH_UDEVD_KILLER], [test "x$enable_udevd_killer" != xno])
+
+# ------------------------------------------------------------------------------
+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]),
+ [case "${enableval}" in
+ yes) enable_frequent_fstrim=yes ;;
+ no) enable_frequent_fstrim=no ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-frequent-fstrim) ;;
+ esac],
+ enable_frequent_fstrim=no)
+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
+
+ prefix: ${prefix}
+ rootprefix: ${with_rootprefix}
+ sysconf dir: ${sysconfdir}
+ datarootdir: ${datarootdir}
+ lib dir: ${libdir}
+ 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}
+])
diff --git a/packaging/system-plugin-common.manifest b/packaging/system-plugin-common.manifest
new file mode 100644
index 0000000..93c2194
--- /dev/null
+++ b/packaging/system-plugin-common.manifest
@@ -0,0 +1,12 @@
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+ <assign>
+ <filesystem path="/bin/*" label="_" exec_label="none" />
+ <filesystem path="/sbin/*" label="_" exec_label="none" />
+ <filesystem path="/usr/bin/*" label="_" exec_label="none" />
+ <filesystem path="/usr/sbin/*" label="_" exec_label="none" />
+ <filesystem path="/etc/rc.d/*" label="_" exec_label="none" />
+ </assign>
+</manifest>
diff --git a/packaging/system-plugin-common.spec b/packaging/system-plugin-common.spec
new file mode 100644
index 0000000..cb66572
--- /dev/null
+++ b/packaging/system-plugin-common.spec
@@ -0,0 +1,179 @@
+###########################
+# Default feature config. #
+###########################
+
+# udev daemon killer unit
+%define WITH_UDEVD_KILLER 0
+# If window manager exist then waiting unit will be installed.
+%define WITH_WMREADY 1
+
+%define WITH_FREQUENT_FSTRIM 0
+
+%if "%{?tizen_profile_name}" == "wearable"
+%define WITH_FREQUENT_FSTRIM 1
+%define dirty_writeback_centisecs 1000
+%endif
+
+Name: system-plugin-common
+Summary: system common file of system
+Version: 0.0.01
+Release: 1
+License: Apache-2.0
+Group: System/Base
+ExclusiveArch: %arm
+Source: %{name}-%{version}.tar.gz
+Source1001: %{name}.manifest
+
+BuildRequires: autoconf
+BuildRequires: automake
+BuildRequires: libtool
+BuildRequires: kernel-headers
+BuildRequires: pkgconfig(dbus-1)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(gio-2.0)
+
+Requires: e2fsprogs
+Requires: /bin/grep
+Requires: /usr/bin/awk
+Requires: psmisc
+Requires(post): coreutils
+
+%description
+Startup files
+
+%prep
+%setup -q
+
+%build
+cp %{SOURCE1001} .
+
+./autogen.sh
+%configure CFLAGS='-g -O0 -Werror' \
+ --prefix=%{_prefix} \
+%if ! %{WITH_WMREADY}
+ --disable-wmready \
+%endif
+%if %{WITH_UDEVD_KILLER}
+ --enable-udevd-killer \
+%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}
+
+%install
+%make_install
+
+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
+
+%files
+%defattr(-,root,root,-)
+%{_datadir}/license/%{name}
+%{_sysconfdir}/systemd/default-extra-dependencies/ignore-units
+%{_bindir}/change-booting-mode.sh
+
+# systemd service units
+%{_libdir}/systemd/system/tizen-generate-env.service
+%{_libdir}/systemd/system/basic.target.wants/tizen-generate-env.service
+%if %{WITH_WMREADY}
+%{_libdir}/systemd/system/wm_ready.service
+%{_libdir}/systemd/system/tizen-boot.target.wants/wm_ready.service
+%endif
+%{_libdir}/systemd/system/check-mount.service
+%{_libdir}/systemd/system/tizen-system.target.wants/check-mount.service
+
+# system initialize units
+%{_libdir}/systemd/system/tizen-init.target
+%{_libdir}/systemd/system/tizen-init-check.service
+%{_libdir}/systemd/system/basic.target.wants/tizen-init-check.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
+
+# fstrim units
+%{_bindir}/tizen-fstrim-on-charge.sh
+%{_libdir}/systemd/system/tizen-fstrim-user.service
+%{_libdir}/systemd/system/tizen-fstrim-user.timer
+
+# readahead units
+%{_libdir}/systemd/system/tizen-readahead-collect.service
+%{_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
+
+# udev daemon killer
+%if %{WITH_UDEVD_KILLER}
+%{_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
index 0000000..ed45cb6
--- /dev/null
+++ b/rules/51-tizen-udev-default.rules
@@ -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"
diff --git a/scripts/change-booting-mode.sh b/scripts/change-booting-mode.sh
new file mode 100644
index 0000000..2e67a92
--- /dev/null
+++ b/scripts/change-booting-mode.sh
@@ -0,0 +1,112 @@
+#!/bin/sh
+#
+# Copyright 2010
+# Read the file COPYING
+#
+# Authors: Yeongil Jang
+#
+# Copyright Samsung Electronics
+#
+
+# print help message
+do_help()
+{
+ /bin/cat >&2 <<EOF
+change-booting-mode: usage:
+ -?/--help this message
+ --fota reboot for fota update (Firmware update On The Air)
+ --fus reboot for fus update (Firmware Update Service)
+ --update change system state for developer update
+EOF
+}
+
+# get and check specified options
+do_options()
+{
+ # note: default settings have already been loaded
+
+ while [ "$#" -ne 0 ]
+ do
+ arg=`/usr/bin/printf %s $1 | /bin/awk -F= '{print $1}'`
+ val=`/usr/bin/printf %s $1 | /bin/awk -F= '{print $2}'`
+ shift
+ if test -z "$val"; then
+ local possibleval=$1
+ /usr/bin/printf %s $1 "$possibleval" | /bin/grep ^- >/dev/null 2>&1
+ if test "$?" != "0"; then
+ val=$possibleval
+ if [ "$#" -ge 1 ]; then
+ shift
+ fi
+ fi
+ fi
+
+ case "$arg" in
+
+ --fota)
+ echo "Setting fota update mode" >&2
+ STATUS_DIR=/opt/data/recovery
+ DELTA_PATH_FILE=${STATUS_DIR}/DELTA.PATH
+ if [ ! -d ${STATUS_DIR} ]; then
+ echo ">> ${STATUS_DIR} does not exist. create one"
+ if [ -f ${STATUS_DIR} ]; then
+ /bin/rm -f ${STATUS_DIR}
+ fi
+ /bin/mkdir -p ${STATUS_DIR}
+ fi
+ echo $val > ${DELTA_PATH_FILE}
+ cmd="fota"
+ ;;
+ --fus)
+ echo "Setting fus update mode" >&2
+ cmd="download"
+ echo "kill mtp-ui, data-router" >> /opt/var/log/fus_update.log 2>&1
+ /usr/bin/killall mtp-ui >> /opt/var/log/fus_update.log 2>&1
+ /usr/bin/killall data-router >> /opt/var/log/fus_update.log 2>&1
+ /bin/umount /dev/gadget >> /opt/var/log/fus_update.log 2>&1
+ /sbin/lsmod >> /opt/var/log/fus_update.log 2>&1
+ /sbin/rmmod g_samsung >> /opt/var/log/fus_update.log 2>&1
+ ;;
+ --update)
+ echo "Setting update mode for engineers" >&2
+# echo 1 > /sys/power/noresume
+# 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
+ 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
+ ;;
+ -?|--help)
+ do_help
+ exit 0
+ ;;
+ *)
+ echo "Unknown option \"$arg\". See --help" >&2
+ do_help
+ exit 0
+ ;;
+ esac
+ done
+}
+
+## main
+
+if test -z "$1"; then
+ do_help
+ exit 0
+fi
+
+do_options $@
+/bin/sync
+/sbin/reboot $cmd
diff --git a/scripts/cleanup-storage.sh b/scripts/cleanup-storage.sh
new file mode 100644
index 0000000..bcbed99
--- /dev/null
+++ b/scripts/cleanup-storage.sh
@@ -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
diff --git a/scripts/tizen-boot.sh.in b/scripts/tizen-boot.sh.in
new file mode 100644
index 0000000..e9f974a
--- /dev/null
+++ b/scripts/tizen-boot.sh.in
@@ -0,0 +1,112 @@
+#!/bin/sh
+
+TIZEN_LABEL="tizen"
+
+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}')
+
+ # 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
+
+ # 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
+
+ # 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
+
+ # 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
+
+ # 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
+}
+
+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
+}
+
+# !!! 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
diff --git a/scripts/tizen-fstrim-on-charge.sh b/scripts/tizen-fstrim-on-charge.sh
new file mode 100644
index 0000000..9aab820
--- /dev/null
+++ b/scripts/tizen-fstrim-on-charge.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+if [ "$#" -ne 1 ];then
+ 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
+else
+ CHARGE_NOW_VALUE=`/bin/cat $CHARGE_NOW_FILE`
+fi
+
+if [ "$CHARGE_NOW_VALUE" -gt 0 ];then
+ echo "Do fstrim."
+ /sbin/fstrim $*
+else
+ echo "Not on charging."
+fi
diff --git a/src/ghost/ghost.c b/src/ghost/ghost.c
new file mode 100644
index 0000000..e9d0bc0
--- /dev/null
+++ b/src/ghost/ghost.c
@@ -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
index 0000000..5815921
--- /dev/null
+++ b/src/ghost/ghost.conf.m4
@@ -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
index 0000000..5f38eee
--- /dev/null
+++ b/src/shared/conf-parser.c
@@ -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
index 0000000..9ccfc08
--- /dev/null
+++ b/src/shared/conf-parser.h
@@ -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
index 0000000..387f961
--- /dev/null
+++ b/src/shared/dbus-common.h
@@ -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
index 0000000..83ef0b6
--- /dev/null
+++ b/src/shared/fileio.c
@@ -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
index 0000000..1713535
--- /dev/null
+++ b/src/shared/fileio.h
@@ -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
index 0000000..5770d4b
--- /dev/null
+++ b/src/shared/macro.h
@@ -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
index 0000000..c484095
--- /dev/null
+++ b/src/shared/systemd.c
@@ -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
index 0000000..aa29e1c
--- /dev/null
+++ b/src/shared/systemd.h
@@ -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
index 0000000..2d98f1a
--- /dev/null
+++ b/src/shared/util.c
@@ -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
index 0000000..4340874
--- /dev/null
+++ b/src/shared/util.h
@@ -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
index 0000000..4225340
--- /dev/null
+++ b/sysctl.d/50-tizen-default.conf.in
@@ -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/check-mount.service b/units/check-mount.service
new file mode 100644
index 0000000..9eede2a
--- /dev/null
+++ b/units/check-mount.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Check Mount
+ConditionPathIsMountPoint=!/opt/usr
+After=tizen-boot.target starter.service
+Requires=tizen-boot.target
+Before=tizen-system.target
+
+[Service]
+Type=oneshot
+ExecStart=/bin/sh -c 'while [ "z`/bin/grep /opt/usr /proc/mounts`" == "z" ]; do /bin/sleep 0.5; done'
+ExecStartPost=/bin/sleep 3
+
+[Install]
+WantedBy=tizen-system.target
diff --git a/units/cleanup-storage.service b/units/cleanup-storage.service
new file mode 100644
index 0000000..426a02d
--- /dev/null
+++ b/units/cleanup-storage.service
@@ -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
index 0000000..c94c753
--- /dev/null
+++ b/units/cleanup-storage.timer
@@ -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
index 0000000..af5f376
--- /dev/null
+++ b/units/ghost.service
@@ -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
index 0000000..b62d0d6
--- /dev/null
+++ b/units/init-conf.service
@@ -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/systemd-udevd-kill.service b/units/systemd-udevd-kill.service
new file mode 100644
index 0000000..609d0f4
--- /dev/null
+++ b/units/systemd-udevd-kill.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Stop systemd-udevd service
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/systemctl stop systemd-udevd.service
+ExecStartPost=/usr/bin/systemctl stop systemd-udevd-control.socket
+ExecStartPost=/usr/bin/systemctl stop systemd-udevd-kernel.socket
diff --git a/units/systemd-udevd-kill.timer b/units/systemd-udevd-kill.timer
new file mode 100644
index 0000000..85624e7
--- /dev/null
+++ b/units/systemd-udevd-kill.timer
@@ -0,0 +1,9 @@
+[Unit]
+Description=Stop systemd-udevd 30s After Completed Startup
+DefaultDependencies=no
+Conflicts=shutdown.target
+After=default.target
+Before=shutdown.target
+
+[Timer]
+OnActiveSec=30s
diff --git a/units/tizen-boot.target b/units/tizen-boot.target
new file mode 100644
index 0000000..1533be5
--- /dev/null
+++ b/units/tizen-boot.target
@@ -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
diff --git a/units/tizen-fstrim-user.service b/units/tizen-fstrim-user.service
new file mode 100644
index 0000000..a0cfe33
--- /dev/null
+++ b/units/tizen-fstrim-user.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Discard unused blocks on user partition
+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-fstrim-user.timer.m4 b/units/tizen-fstrim-user.timer.m4
new file mode 100644
index 0000000..8ebabf3
--- /dev/null
+++ b/units/tizen-fstrim-user.timer.m4
@@ -0,0 +1,8 @@
+[Unit]
+Description=Timer for tizen-fstrim
+
+[Timer]
+m4_ifdef(`WITH_FREQUENT_FSTRIM',
+`OnBootSec=30
+OnUnitActiveSec=3h',
+`OnCalendar=*-*-* 06:00:00')
diff --git a/units/tizen-generate-env.service b/units/tizen-generate-env.service
new file mode 100644
index 0000000..ae5bc98
--- /dev/null
+++ b/units/tizen-generate-env.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Generate environment from /etc/profile.d
+DefaultDependencies=no
+After=opt.mount
+Before=basic.target
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/env -i sh -c 'source /etc/profile; env | /bin/egrep -v "^(HOME|PWD|SHLVL|_)=" > /run/tizen-mobile-env'
+
+[Install]
+WantedBy=basic.target
diff --git a/units/tizen-init-check.service.in b/units/tizen-init-check.service.in
new file mode 100644
index 0000000..31ec3ca
--- /dev/null
+++ b/units/tizen-init-check.service.in
@@ -0,0 +1,11 @@
+[Unit]
+Description=Tizen Initialized check
+DefaultDependencies=no
+After=opt.mount
+Before=tizen-init-done.service tizen-initial-boot-done.service
+ConditionPathExists=@INITAILBOOT_DONE@
+ConditionPathExists=!@INITIALIZE_DONE@
+RefuseManualStart=yes
+
+[Service]
+ExecStart=/usr/bin/systemctl start tizen-init.target
diff --git a/units/tizen-init-done.service.in b/units/tizen-init-done.service.in
new file mode 100644
index 0000000..df4c5c1
--- /dev/null
+++ b/units/tizen-init-done.service.in
@@ -0,0 +1,11 @@
+[Unit]
+Description=Tizen initialized flag done
+After=default.target
+ConditionPathExists=!@INITIALIZE_DONE@
+RefuseManualStart=yes
+
+[Service]
+ExecStart=/bin/touch @INITIALIZE_DONE@
+
+[Install]
+WantedBy=tizen-init.target
diff --git a/units/tizen-init.target b/units/tizen-init.target
new file mode 100644
index 0000000..8c7ce15
--- /dev/null
+++ b/units/tizen-init.target
@@ -0,0 +1,5 @@
+[Unit]
+Description=Tizen Initialization
+Conflicts=emergency.service emergency.target
+Wants=local-fs.target swap.target
+After=local-fs.target swap.target emergency.service emergency.target
diff --git a/units/tizen-initial-boot-done.service.in b/units/tizen-initial-boot-done.service.in
new file mode 100644
index 0000000..7e8ae55
--- /dev/null
+++ b/units/tizen-initial-boot-done.service.in
@@ -0,0 +1,11 @@
+[Unit]
+Description=Tizen initial boot flag generate
+After=default.target
+ConditionPathExists=!@INITAILBOOT_DONE@
+RefuseManualStart=yes
+
+[Service]
+ExecStart=/bin/touch @INITAILBOOT_DONE@
+
+[Install]
+WantedBy=default.target
diff --git a/units/tizen-journal-flush.service b/units/tizen-journal-flush.service
new file mode 100644
index 0000000..9a2d2ee
--- /dev/null
+++ b/units/tizen-journal-flush.service
@@ -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
diff --git a/units/tizen-readahead-collect-stop.service b/units/tizen-readahead-collect-stop.service
new file mode 100644
index 0000000..9d4aeaa
--- /dev/null
+++ b/units/tizen-readahead-collect-stop.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Stop Read-Ahead Data Collection
+DefaultDependencies=no
+Conflicts=shutdown.target
+After=tizen-readahead-collect.service boot-animation.service
+Before=shutdown.target tizen-system.target
+ConditionVirtualization=no
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/systemd-notify --readahead=done
+
+[Install]
+Also=tizen-readahead-collect.service
diff --git a/units/tizen-readahead-collect.service.in b/units/tizen-readahead-collect.service.in
new file mode 100644
index 0000000..8b0c5c3
--- /dev/null
+++ b/units/tizen-readahead-collect.service.in
@@ -0,0 +1,20 @@
+[Unit]
+Description=Collect Read-Ahead Data
+DefaultDependencies=no
+Wants=tizen-readahead-collect-stop.service
+Conflicts=shutdown.target
+After=smack.service smack-default-labeling.service tizen-readahead-replay.service
+Before=sysinit.target shutdown.target
+ConditionPathExists=!/run/systemd/readahead/cancel
+ConditionPathExists=!/run/systemd/readahead/done
+ConditionPathExists=!@READAHEAD_DIR@/.readahead
+ConditionVirtualization=no
+
+[Service]
+Type=notify
+ExecStart=@rootlibexecdir@/systemd-readahead collect --savedir=@READAHEAD_DIR@
+RemainAfterExit=yes
+StandardOutput=null
+
+[Install]
+WantedBy=tizen-init.target
diff --git a/units/tizen-readahead-replay.service.in b/units/tizen-readahead-replay.service.in
new file mode 100644
index 0000000..22f00dd
--- /dev/null
+++ b/units/tizen-readahead-replay.service.in
@@ -0,0 +1,19 @@
+[Unit]
+Description=Replay Read-Ahead Data
+DefaultDependencies=no
+Conflicts=shutdown.target
+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=@rootlibexecdir@/systemd-readahead replay --savedir=@READAHEAD_DIR@
+RemainAfterExit=yes
+StandardOutput=null
+OOMScoreAdjust=1000
+
+[Install]
+WantedBy=graphical.target
diff --git a/units/tizen-runtime.target b/units/tizen-runtime.target
new file mode 100644
index 0000000..b1bc216
--- /dev/null
+++ b/units/tizen-runtime.target
@@ -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
index 0000000..4240819
--- /dev/null
+++ b/units/tizen-system.target
@@ -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
diff --git a/units/wm_ready.service b/units/wm_ready.service
new file mode 100644
index 0000000..e3f260b
--- /dev/null
+++ b/units/wm_ready.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=waiting for window mananger
+After=xorg.service
+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