From: taeyoung Date: Thu, 26 Nov 2015 09:37:14 +0000 (+0900) Subject: crash: add crash module to use coredumpctl X-Git-Tag: accepted/tizen/mobile/20151208.130302~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3611bc256d640797c32bc2094d0dec5392a4b3ff;p=platform%2Fcore%2Fsystem%2Fcrash-worker.git crash: add crash module to use coredumpctl - For Tizen 2.4, Crash-manager and sys-assert are used to getting crash information. - For Tizen 3.0 coredumpctl is supported, and thus coredumpctl is used to get information and store coredump file. Signed-off-by: taeyoung --- diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2e1fb00 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,9 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(crash-worker C) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + +# Sub modules +ADD_SUBDIRECTORY(src/crash-manager) +ADD_SUBDIRECTORY(src/dump_systemstate) + diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..8aa906c --- /dev/null +++ b/LICENSE @@ -0,0 +1,205 @@ + + 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/NOTICE b/NOTICE new file mode 100755 index 0000000..579ba56 --- /dev/null +++ b/NOTICE @@ -0,0 +1,3 @@ +Copyright (c) Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under Apache License, Version 2. +Please, see the LICENSE.Apache-2.0 file for Apache License terms and conditions. diff --git a/packaging/crash-worker.manifest b/packaging/crash-worker.manifest new file mode 100644 index 0000000..97e8c31 --- /dev/null +++ b/packaging/crash-worker.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec new file mode 100644 index 0000000..f70f592 --- /dev/null +++ b/packaging/crash-worker.spec @@ -0,0 +1,48 @@ +Name: crash-worker +Summary: Crash-manager +Version: 0.2.0 +Release: 1 +Group: Framework/system +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +Source1001: crash-worker.manifest +BuildRequires: pkgconfig(dlog) +BuildRequires: cmake + +Requires(post): coreutils +Requires(post): tar +Requires(post): gzip + +%description +crash-manager + +%prep +%setup -q + +%build +cp %{SOURCE1001} . + +export CFLAGS+=" -Werror" + +%cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install +mkdir -p %{buildroot}/opt/usr/share/crash +mkdir -p %{buildroot}/opt/usr/share/crash/dump + +%install_service sysinit.target.wants crash-manager.service + +%files +%license LICENSE +%manifest crash-worker.manifest +%defattr(-,system,system,-) +%dir /opt/usr/share/crash +%dir /opt/usr/share/crash/dump +%attr(0755,system,system)/usr/bin/dump_systemstate +%{_bindir}/crash-manager.sh +%{_bindir}/set_corepattern.sh +%{_unitdir}/crash-manager.service +%{_unitdir}/sysinit.target.wants/crash-manager.service diff --git a/src/crash-manager/CMakeLists.txt b/src/crash-manager/CMakeLists.txt new file mode 100644 index 0000000..f46f0ea --- /dev/null +++ b/src/crash-manager/CMakeLists.txt @@ -0,0 +1,18 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +SET(CRASH_MANAGER "crash-manager") + +INSTALL(FILES ${CMAKE_SOURCE_DIR}/src/${CRASH_MANAGER}/${CRASH_MANAGER}.sh + DESTINATION /usr/bin + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + +INSTALL(FILES ${CMAKE_SOURCE_DIR}/src/${CRASH_MANAGER}/set_corepattern.sh + DESTINATION /usr/bin + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + +INSTALL(FILES ${CMAKE_SOURCE_DIR}/src/${CRASH_MANAGER}/${CRASH_MANAGER}.service + DESTINATION /usr/lib/systemd/system + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/src/crash-manager/crash-manager.service b/src/crash-manager/crash-manager.service new file mode 100644 index 0000000..cf013e6 --- /dev/null +++ b/src/crash-manager/crash-manager.service @@ -0,0 +1,12 @@ +[Unit] +Description=Set core pattern +DefaultDependencies=no +Before=sysinit.target + +[Service] +Type=oneshot +ExecStart=/usr/bin/set_corepattern.sh + +[Install] +WantedBy=sysinit.target + diff --git a/src/crash-manager/crash-manager.sh b/src/crash-manager/crash-manager.sh new file mode 100644 index 0000000..bf960a1 --- /dev/null +++ b/src/crash-manager/crash-manager.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +process="$1" +user="$2" +group="$3" +signal="$4" +time="$5" +app="$6" + +/usr/lib/systemd/systemd-coredump "$process" "$user" "$group" "$signal" "$time" "$app" + +rootpath=/opt/usr/share/crash/dump +name="$app"_"$process"_"$time" +path="$rootpath"/"$name" +info="$path"/"$name".info +dump="$path"/"$name".coredump +log="$path"/"$name".log + +/usr/bin/mkdir -p "$rootpath" +/usr/bin/mkdir -p "$path" + +/usr/bin/coredumpctl dump "$process" --output="$dump" + +/usr/bin/coredumpctl info "$process" >> "$info" +/usr/bin/coredumpctl dump "$process" --output="$dump" +/usr/bin/dump_systemstate -d -k -f "$log" diff --git a/src/crash-manager/set_corepattern.sh b/src/crash-manager/set_corepattern.sh new file mode 100644 index 0000000..d622400 --- /dev/null +++ b/src/crash-manager/set_corepattern.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +/usr/bin/echo "|/usr/bin/crash-manager.sh %p %u %g %s %t %e" > /proc/sys/kernel/core_pattern diff --git a/src/dump_systemstate/CMakeLists.txt b/src/dump_systemstate/CMakeLists.txt new file mode 100755 index 0000000..8625c10 --- /dev/null +++ b/src/dump_systemstate/CMakeLists.txt @@ -0,0 +1,27 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(dump_systemstate C) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src) +SET(SRCS + dump_systemstate.c + ${CMAKE_SOURCE_DIR}/src/shared/util.c + ) + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED dlog) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer -finstrument-functions") + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +MESSAGE("FLAGS: ${CMAKE_C_FLAGS}") + +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS}) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/src/dump_systemstate/dump_systemstate.c b/src/dump_systemstate/dump_systemstate.c new file mode 100644 index 0000000..be8dd74 --- /dev/null +++ b/src/dump_systemstate/dump_systemstate.c @@ -0,0 +1,218 @@ +/* + * dump_systemstate + * + * Copyright (c) 2012 - 2013 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. + */ + +/** + * @file dump_systemstate.c + * @brief dump system states. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "shared/util.h" + +#define FILE_PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) +static struct dump_item { + const char *title; + const char *path; +} dump_item[] = { + {"==== Binary version " , "/etc/info.ini"}, + {"==== Tizen version " , "/etc/tizen-release"}, + {"==== Kernel version " , "/proc/version"}, + {"==== Boot arguments " , "/proc/cmdline"}, + {"==== CPU & system architecture " , "/proc/cpuinfo"}, + {"==== System uptime " , "/proc/uptime"}, + {"==== System statistics " , "/proc/stat"}, + {"==== System memory usage " , "/proc/meminfo"}, + {"==== Device major numbers " , "/proc/devices"}, + {"==== System disk I/O satistics " , "/proc/diskstats"}, +}; + +static void usage() { + fprintf(stderr, "usage: dump_systemstate [-k] [-d] [-f file]\n" + " -f: write to file (instead of stdout)\n" + " -k: dump kernel messages (only root)\n" + " -d: dump dlog messages\n" + ); +} + +/* get disk used percentage */ +static int get_disk_used_percent(const char *path) +{ + struct statfs lstatfs; + int percent; + + if (!path) + return -1; + + if (statfs(path, &lstatfs) < 0) + return -1; + percent = (((lstatfs.f_blocks - lstatfs.f_bfree) * 1000) / (lstatfs.f_blocks)) + 9; + percent = percent/10; + return percent; +} + +int main(int argc, char *argv[]) { + int c, ret, i, is_root, dpercent; + const char *arg_file = NULL; + int out_fd = -1; + bool arg_dlog = false; + bool arg_dmesg = false; + char timestr[80]; + time_t cur_time; + struct tm gm_tm; + struct tm loc_tm; + + while ((c = getopt(argc, argv, "hf:kd")) != -1) { + switch (c) { + case 'd': + arg_dlog = true; + break; + case 'k': + arg_dmesg = true; + break; + case 'f': + arg_file = optarg; + break; + case '?': printf("\n"); + case 'h': + usage(); + ret = 0; + goto exit; + } + } + ret = 0; + cur_time = time(NULL); + gmtime_r(&cur_time, &gm_tm); + localtime_r(&cur_time, &loc_tm); + is_root = !(geteuid()); + + /* open output file */ + if (arg_file == NULL) { + out_fd = STDOUT_FILENO; + } else { + out_fd = open(arg_file, O_WRONLY | O_TRUNC | O_CREAT, FILE_PERM); + if (out_fd < 0) { + perror ("couldn't open output file"); + ret = out_fd; + goto exit; + } + } + /* print timestamp */ + strftime(timestr, sizeof(timestr), + "%Y-%m-%d %H:%M:%S%z", &loc_tm); + fprintf_fd(out_fd, "dump_systemstate: %s\n", timestr); + + for (i = 0; i < ARRAY_SIZE(dump_item); i++) { + fsync(out_fd); + fprintf_fd(out_fd, "\n%s(%s)\n", + dump_item[i].title, dump_item[i].path); + ret = dump_file_write_fd((char *)dump_item[i].path, out_fd); + if (ret < 0) + goto exit_close; + } + fprintf_fd(out_fd, "\n"); + + fprintf_fd(out_fd, "\n==== System disk space usage (/bin/df -h)\n"); + ret = run_command_write_fd("/bin/df -h", out_fd); + if (ret < 0) + goto exit_close; + + dpercent = get_disk_used_percent("/opt"); + if (90 < dpercent) { + fprintf_fd(out_fd, "\n==== System disk space usage detail - %d\% (/bin/du -ah /opt)\n", dpercent); + ret = run_command_write_fd("/usr/bin/du -ah /opt --exclude=/opt/usr", out_fd); + if (ret < 0) + goto exit_close; + } + fprintf_fd(out_fd, "\n==== System timezone (ls -al /opt/etc/localtime)\n"); + ret = run_command_write_fd("ls -al /opt/etc/localtime", out_fd); + if (ret < 0) + goto exit_close; + + fprintf_fd(out_fd, "\n==== System summary (/usr/bin/top -bcH -n 1)\n"); + ret = run_command_write_fd("COLUMNS=200 /usr/bin/top -bcH -n 1", out_fd); + if (ret < 0) + goto exit_close; + + fprintf_fd(out_fd, "\n==== Current processes (/bin/ps auxfw)\n"); + ret = run_command_write_fd("/bin/ps auxfw", out_fd); + if (ret < 0) + goto exit_close; + + if (is_root) { + fprintf_fd(out_fd, "\n==== System memory statistics (/usr/bin/memps -v)\n"); + ret = run_command_write_fd("/usr/bin/memps -v", out_fd); + if (ret < 0) + goto exit_close; + + fprintf_fd(out_fd, "\n==== System configuration (/usr/bin/vconftool get memory, db, file)\n"); + ret = run_command_write_fd("/usr/bin/vconftool get memory/ -r", out_fd); + if (ret < 0) + goto exit_close; + + ret = run_command_write_fd("/usr/bin/vconftool get db/ -r", out_fd); + if (ret < 0) + goto exit_close; + + ret = run_command_write_fd("/usr/bin/vconftool get file/ -r", out_fd); + if (ret < 0) + goto exit_close; + } + + if (arg_dmesg && is_root) { + fprintf_fd(out_fd, "\n==== Kernel messages (TZ=UTC /bin/dmesg -T)\n"); + ret = run_command_write_fd("TZ=UTC /bin/dmesg -T", out_fd); + if (ret < 0) + goto exit_close; + } + + if (arg_dlog) { + fprintf_fd(out_fd, "\n==== main log messages (/dev/log_main)\n"); + ret = run_command_write_fd("/usr/bin/dlogutil -d -v dump -b main", out_fd); + if (ret < 0) + goto exit_close; + + if(is_root) { + fprintf_fd(out_fd, "\n==== system log messages (/dev/log_system)\n"); + ret = run_command_write_fd("/usr/bin/dlogutil -d -v dump -b system", out_fd); + if (ret < 0) + goto exit_close; + + fprintf_fd(out_fd, "\n==== radio log messages (/dev/log_radio)\n"); + ret = run_command_write_fd("/usr/bin/dlogutil -d -v dump -b radio", out_fd); + if (ret < 0) + goto exit_close; + } + } + +exit_close: + if (arg_file) + close(out_fd); +exit: + return ret; +} diff --git a/src/shared/log.h b/src/shared/log.h new file mode 100644 index 0000000..6a38a4c --- /dev/null +++ b/src/shared/log.h @@ -0,0 +1,38 @@ +/* + * crash-manager + * Copyright (c) 2012-2013 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. + */ + + + +#ifndef __CRASH_LOG_H__ +#define __CRASH_LOG_H__ + +#ifndef LOG_TAG +#define LOG_TAG "CRASH_MANAGER" +#endif +#include + +#define _D(fmt, arg...) SLOGD(fmt, ##arg) +#define _I(fmt, arg...) SLOGI(fmt, ##arg) +#define _W(fmt, arg...) SLOGW(fmt, ##arg) +#define _E(fmt, arg...) SLOGE(fmt, ##arg) +#define _SD(fmt, arg...) SECURE_SLOGD(fmt, ##arg) +#define _SI(fmt, arg...) SECURE_SLOGI(fmt, ##arg) +#define _SW(fmt, arg...) SECURE_SLOGW(fmt, ##arg) +#define _SE(fmt, arg...) SECURE_SLOGE(fmt, ##arg) + +#endif +/* __CRASH_LOG_H__ */ diff --git a/src/shared/util.c b/src/shared/util.c new file mode 100644 index 0000000..3797f17 --- /dev/null +++ b/src/shared/util.c @@ -0,0 +1,522 @@ +/* + * crash-manager + * Copyright (c) 2012-2013 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. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "log.h" + +int system_command(char *command) +{ + int pid = 0, + status = 0; + const char *environ[] = { NULL }; + + if (command == NULL) + return -1; + pid = fork(); + if (pid == -1) + return -1; + if (pid == 0) { + char *argv[4]; + argv[0] = "sh"; + argv[1] = "-c"; + argv[2] = (char *)command; + argv[3] = 0; + execve("/bin/sh", argv, (char **)environ); + exit(127); + } + do { + if (waitpid(pid, &status, 0) == -1) { + if (errno != EINTR) + return -1; + } else { + if (WIFEXITED(status)) { + return WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + return WTERMSIG(status); + } else if (WIFSTOPPED(status)) { + return WSTOPSIG(status); + } + } + } while (!WIFEXITED(status) && !WIFSIGNALED(status)); + + return 0; +} + +int system_command_with_timeout(int timeout_seconds, char *command) +{ + const char *environ[] = { NULL }; + + if (command == NULL) + return -1; + clock_t start = clock(); + pid_t pid = fork(); + /* handle error case */ + if (pid < 0) { + _E("fork: %s\n", strerror(errno)); + return pid; + } + /* handle child case */ + if (pid == 0) { + char *argv[4]; + argv[0] = "sh"; + argv[1] = "-c"; + argv[2] = (char *)command; + argv[3] = 0; + + execve("/bin/sh", argv, (char **)environ); + _SI("exec(%s): %s\n", command, strerror(errno)); + _exit(-1); + } + /* handle parent case */ + for (;;) { + int status; + pid_t p = waitpid(pid, &status, WNOHANG); + float elapsed = (float) (clock() - start) / CLOCKS_PER_SEC; + if (p == pid) { + if (WIFSIGNALED(status)) + _SI("%s: Killed by signal %d\n", command, WTERMSIG(status)); + else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) + _SI("%s: Exit code %d\n", command, WEXITSTATUS(status)); + return WEXITSTATUS(status); + } + if (timeout_seconds && elapsed > timeout_seconds) { + _SI("%s: Timed out after %.1fs (killing pid %d)\n", + command, elapsed, pid); + kill(pid, SIGTERM); + return -1; + } + /* poll every 0.1 sec */ + usleep(100000); + } +} + +/* WARNING : formatted string buffer is limited to 1024 byte */ +int fprintf_fd(int fd, const char *fmt, ...) +{ + int n; + int ret; + char buff[1024]; + va_list args; + + va_start(args, fmt); + n = vsnprintf(buff, 1024 - 1, fmt, args); + ret = write(fd, buff, n); + va_end(args); + return ret; +} + +int file_exist(const char *file) +{ + FILE *fp; + + fp = fopen(file, "r"); + if (fp == NULL) + return -1; + fclose(fp); + return 1; +} + +int write_fd(int fd, const void *buf, int len) +{ + int count; + int total; + total = 0; + while (len) { + count = write(fd, buf, len); + if (count < 0) { + if (total) + return total; + return count; + } + total += count; + buf = ((const char *)buf) + count; + len -= count; + } + return total; +} + +int copy_file(char *src, char *dst) +{ + int sfd; + int dfd; + char buf[PIPE_BUF]; + + if(!src || !dst) { + _E("Invalid argument\n"); + return -1; + } + sfd = open(src, O_RDONLY); + if (sfd < 0) { + _E("Failed to open (%s)\n", src); + return -1; + } + dfd = open(dst, O_WRONLY|O_CREAT|O_EXCL, 0644); + if (dfd < 0) { + close(sfd); + _SE("Failed to open (%s)\n", dst); + return -1; + } + for (;;) { + int ret = read(sfd, buf, sizeof(buf)); + if (ret > 0) + ret = write_fd(dfd, buf, ret); + if (ret <= 0) + break; + } + close(sfd); + close(dfd); + return 1; +} + +int cat_file(char *src, char *dst) +{ + int sfd; + int dfd; + char buf[PIPE_BUF]; + + if(!src || !dst) { + _E("Invalid argument\n"); + return -1; + } + sfd = open(src, O_RDONLY); + if (sfd < 0) { + _SE("Failed to open (%s)\n", src); + return -1; + } + dfd = open(dst, O_WRONLY|O_APPEND); + if (dfd < 0) { + close(sfd); + _SE("Failed to open (%s)\n", dst); + return -1; + } + for (;;) { + int ret = read(sfd, buf, sizeof(buf)); + if (ret > 0) + ret = write_fd(dfd, buf, ret); + if (ret <= 0) + break; + } + close(sfd); + close(dfd); + return 1; +} + +int move_file(char *src, char *dst) +{ + if (copy_file(src, dst) < 0) + return -1; + if (unlink(src) < 0) + return -1; + return 1; +} + +int dump_file_write_fd(char *src, int dfd) +{ + int sfd; + char buf[PIPE_BUF]; + + if(!src) { + _E("Invalid argument\n"); + return -1; + } + sfd = open(src, O_RDONLY); + if (sfd < 0) { + _SE("Failed to open (%s)\n", src); + return -1; + } + for (;;) { + int ret = read(sfd, buf, sizeof(buf)); + if (ret > 0) + ret = write_fd(dfd, buf, ret); + if (ret <= 0) + break; + } + close(sfd); + return 1; +} + +int run_command_write_fd(char *cmd, int dfd) +{ + FILE *fp; + char buff[PIPE_BUF]; + int ret; + + if (!cmd) { + _E("Invalid argument\n"); + return -1; + } + + fp = popen(cmd, "r"); + if (fp == NULL) { + _E("Failed to popen\n"); + return -1; + } + while(fgets(buff, PIPE_BUF, fp) != NULL) { + write_fd(dfd, buff, strlen(buff)); + } + ret = pclose(fp); + return ret; +} + +static int remove_dir_internal(int fd) +{ + DIR *dir; + struct dirent *de; + int subfd, ret = 0; + + dir = fdopendir(fd); + if (!dir) + return -1; + while ((de = readdir(dir))) { + if (de->d_type == DT_DIR) { + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) + continue; + subfd = openat(fd, de->d_name, O_RDONLY | O_DIRECTORY); + if (subfd < 0) { + _SE("Couldn't openat %s: %s\n", de->d_name, strerror(errno)); + ret = -1; + continue; + } + if (remove_dir_internal(subfd)) { + ret = -1; + } + close(subfd); + if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) { + _SE("Couldn't unlinkat %s: %s\n", de->d_name, strerror(errno)); + ret = -1; + } + } else { + if (unlinkat(fd, de->d_name, 0) < 0) { + _SE("Couldn't unlinkat %s: %s\n", de->d_name, strerror(errno)); + ret = -1; + } + } + } + closedir(dir); + return ret; +} + +int remove_dir(const char *path, int del_dir) +{ + int fd, ret = 0; + + if (!path) + return -1; + fd = open(path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); + if (fd < 0) { + _SE("Couldn't opendir %s: %s\n", path, strerror(errno)); + return -errno; + } + ret = remove_dir_internal(fd); + close(fd); + + if (del_dir) { + if (rmdir(path)) { + _SE("Couldn't rmdir %s: %s\n", path, strerror(errno)); + ret = -1; + } + } + return ret; +} + +int make_dir(const char *path, mode_t mode, const char *grname) +{ + mode_t old_mask; + struct group *group_entry; + int ret; + + if (!grname || !path) + return -1; + if (access(path, F_OK) == 0) + return 0; + old_mask = umask(002); + ret = mkdir(path, mode); + if (ret < 0) + return -1; + group_entry = getgrnam(grname); + if (group_entry == NULL) { + umask(old_mask); + return -1; + } + if (chown(path, 0, group_entry->gr_gid) < 0) + _SW("can't chown (%s)\n", path); + umask(old_mask); + + return 0; +} + +int get_exec_pid(const char *execpath) +{ + DIR *dp; + struct dirent *dentry; + int pid = -1, fd; + int ret; + char buf[PATH_MAX]; + char buf2[PATH_MAX]; + + dp = opendir("/proc"); + if (!dp) { + _E("FAIL: open /proc"); + return -1; + } + + while ((dentry = readdir(dp)) != NULL) { + if (!isdigit(dentry->d_name[0])) + continue; + + pid = atoi(dentry->d_name); + + snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid); + fd = open(buf, O_RDONLY); + if (fd < 0) + continue; + ret = read(fd, buf2, PATH_MAX); + close(fd); + + if (ret < 0 || ret >= PATH_MAX) + continue; + + buf2[ret] = '\0'; + + if (!strcmp(buf2, execpath)) { + closedir(dp); + return pid; + } + } + + errno = ESRCH; + closedir(dp); + return -1; +} + +int get_file_count(char *path) +{ + DIR *dir; + struct dirent *dp; + int count = 0; + + dir = opendir(path); + if (!dir) + return 0; + while ((dp = readdir(dir)) != NULL) { + const char *name = dp->d_name; + /* always skip "." and ".." */ + if (name[0] == '.') { + if (name[1] == 0) + continue; + if ((name[1] == '.') && (name[2] == 0)) + continue; + } + count++; + } + closedir(dir); + return count; +} + +int get_directory_usage(char *path) +{ + DIR *dir; + struct dirent *de; + struct stat st; + size_t usage = 0; + int fd = -1; + + fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); + if (fd < 0) + return -1; + dir = fdopendir(fd); + if (!dir) { + close(fd); + return -1; + } + while ((de = readdir(dir))) { + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) + continue; + if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { + _SE("Failed to fstatat %s: %s\n", de->d_name, strerror(errno)); + continue; + } + usage += st.st_size; + } + closedir(dir); + close(fd); + return usage; +} + + +int validate_env_name(char *name, int len) +{ + char *p; + + if (len <= 0) + return -1; + + if (len > NAME_MAX) + return -1; + + if (name[0] >= '0' && name[0] <= '9') + return -1; + + for (p = name; p < name + len; p++) + if (!((*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9') || + *p == '_')) + return -1; + return 0; +} + +int validate_file_name(char *name, int len) +{ + char *p; + + if (len <= 0) + return -1; + + if (len > NAME_MAX) + return -1; + + if ((name[0] == '-') || (name[0] >= '0' && name[0] <= '9')) + return -1; + + for (p = name; p < name + len; p++) + if (!((*p >= 0x07 && *p <= 0x0C) || + (*p >= 0x20 && *p <= 0x7E))) + return -1; + + return 0; +} +/** + * @} + */ diff --git a/src/shared/util.h b/src/shared/util.h new file mode 100644 index 0000000..299e616 --- /dev/null +++ b/src/shared/util.h @@ -0,0 +1,60 @@ +/* + * crash-manager + * Copyright (c) 2012-2013 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. + */ +#ifndef __DEF_UTIL_H__ +#define __DEF_UTIL_H__ + +#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0])) + +#ifndef __CONSTRUCTOR__ +#define __CONSTRUCTOR__ __attribute__ ((constructor)) +#endif + +int system_command(char *command); + +int system_command_with_timeout(int timeout_seconds, char *command); + +int fprintf_fd(int fd, const char *fmt, ...); + +int write_fd(int fd, const void *buf, int len); + +int copy_file(char *src, char *dst); + +int cat_file(char *src, char *dst); + +int move_file(char *src, char *dst); + +int dump_file_write_fd(char *src, int dfd); + +int run_command_write_fd(char *cmd, int dfd); + +int make_dir(const char *path, mode_t mode, const char *grname); + +int remove_dir(const char *path, int del_dir); + +int get_exec_pid(const char *execpath); + +int get_file_count(char *path); + +int get_directory_usage(char *path); + +int validate_env_name(char *name, int len); + +int validate_file_name(char *name, int len); +/** + * @} + */ +#endif