From: Sungbae Yoo Date: Wed, 3 Aug 2016 09:55:25 +0000 (-0700) Subject: Revert "Move dpm-common codes to klay git" X-Git-Tag: accepted/tizen/common/20160803.193343^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9d8ee2a1845c1ac91a057caff0f28214ea58e500;p=platform%2Fcore%2Fsecurity%2Fdevice-policy-manager.git Revert "Move dpm-common codes to klay git" This reverts commit 4d9d56100691b99eebd6836ef80d6a75b8db844f. Change-Id: I2a4f722901a36879dfdb3a05651dd89bf7b093fd --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 8969033..d82ebbe 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ IF(NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE "DEBUG") ENDIF(NOT CMAKE_BUILD_TYPE) +SET(DPM_COMMON ${PROJECT_SOURCE_DIR}/common) SET(DPM_POLICY ${PROJECT_SOURCE_DIR}/policy) SET(DPM_LIBS ${PROJECT_SOURCE_DIR}/libs) SET(DPM_SERVER ${PROJECT_SOURCE_DIR}/server) @@ -85,6 +86,7 @@ ENDIF(NOT DEFINED SYSTEMD_UNIT_INSTALL_DIR) ADD_DEFINITIONS(-DUG_WAYLAND) +ADD_SUBDIRECTORY(${DPM_COMMON}) ADD_SUBDIRECTORY(${DPM_SERVER}) ADD_SUBDIRECTORY(${DPM_LIBS}) ADD_SUBDIRECTORY(${DPM_TOOLS}) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt new file mode 100755 index 0000000..364441f --- /dev/null +++ b/common/CMakeLists.txt @@ -0,0 +1,62 @@ +# +# Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +# +# 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. +# + +PROJECT(dpm-common) + +SET (COMMON_SOURCES ${DPM_COMMON}/error.cpp + ${DPM_COMMON}/process.cpp + ${DPM_COMMON}/eventfd.cpp + ${DPM_COMMON}/mainloop.cpp + ${DPM_COMMON}/filesystem.cpp + ${DPM_COMMON}/thread-pool.cpp + ${DPM_COMMON}/rmi/socket.cpp + ${DPM_COMMON}/rmi/client.cpp + ${DPM_COMMON}/rmi/message.cpp + ${DPM_COMMON}/rmi/message-composer.cpp + ${DPM_COMMON}/rmi/service.cpp + ${DPM_COMMON}/rmi/connection.cpp + ${DPM_COMMON}/rmi/notification.cpp + ${DPM_COMMON}/audit/logger.cpp + ${DPM_COMMON}/audit/null-sink.cpp + ${DPM_COMMON}/audit/console-sink.cpp + ${DPM_COMMON}/xml/node.cpp + ${DPM_COMMON}/xml/parser.cpp + ${DPM_COMMON}/xml/document.cpp + ${DPM_COMMON}/xml/keepblanks.cpp + ${DPM_COMMON}/db/column.cpp + ${DPM_COMMON}/db/statement.cpp + ${DPM_COMMON}/db/connection.cpp + ${DPM_COMMON}/auth/user.cpp + ${DPM_COMMON}/auth/group.cpp + ${DPM_COMMON}/dbus/error.cpp + ${DPM_COMMON}/dbus/variant.cpp + ${DPM_COMMON}/dbus/connection.cpp +) + +SET (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack") + +ADD_LIBRARY(${PROJECT_NAME} STATIC ${COMMON_SOURCES}) + +PKG_CHECK_MODULES(COMMON_DEPS REQUIRED libxml-2.0 + sqlite3 + gio-2.0 +) + +INCLUDE_DIRECTORIES(SYSTEM ${DPM_COMMON} + ${COMMON_DEPS_INCLUDE_DIRS} +) + +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${COMMON_DEPS_LIBRARIES}) diff --git a/zone/libs/zone/array.h b/common/array.h similarity index 100% rename from zone/libs/zone/array.h rename to common/array.h diff --git a/common/audit/console-sink.cpp b/common/audit/console-sink.cpp new file mode 100644 index 0000000..747fe51 --- /dev/null +++ b/common/audit/console-sink.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +#include "console-sink.h" + +namespace audit { + +void ConsoleLogSink::sink(const std::string& message) +{ + std::cout << message << std::flush; +} + +} // namespace audit diff --git a/common/audit/console-sink.h b/common/audit/console-sink.h new file mode 100644 index 0000000..85dbe27 --- /dev/null +++ b/common/audit/console-sink.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __AUDIT_CONSOLE_LOGSINK_H__ +#define __AUDIT_CONSOLE_LOGSINK_H__ + +#include + +#include "logsink.h" + +namespace audit { + +class ConsoleLogSink : public LogSink { +public: + void sink(const std::string& message) override; +}; + +} // namespace audit +#endif //__AUDIT_CONSOLE_LOGSINK_H__ diff --git a/common/audit/logger.cpp b/common/audit/logger.cpp new file mode 100644 index 0000000..d9c9fb6 --- /dev/null +++ b/common/audit/logger.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include + +#include + +#include "logger.h" +#include "console-sink.h" + +#include "exception.h" + +namespace audit { + +LogLevel Logger::logLevel = LogLevel::Trace; +std::unique_ptr Logger::backend(new ConsoleLogSink()); + +std::string LogLevelToString(const LogLevel level) +{ + switch (level) { + case LogLevel::Error: + return "ERROR"; + case LogLevel::Warning: + return "WARN"; + case LogLevel::Debug: + return "DEBUG"; + case LogLevel::Info: + return "INFO"; + default: + return "UNKNOWN"; + } +} + +void Logger::setLogLevel(const LogLevel level) +{ + Logger::logLevel = level; +} + +LogLevel Logger::getLogLevel(void) +{ + return Logger::logLevel; +} + +void Logger::log(LogLevel severity, + const std::string& file, + const unsigned int line, + const std::string& func, + const std::string& message) +{ + std::ostringstream buffer; + + buffer << LogLevelToString(severity) + << "<" << ::getpid() << ">:" + << file << ":" << line + << " " << func << " " << message + << std::endl; + + Logger::backend->sink(buffer.str()); +} + +} // namespace audit diff --git a/common/audit/logger.h b/common/audit/logger.h new file mode 100644 index 0000000..209aa69 --- /dev/null +++ b/common/audit/logger.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __AUDIT_LOGGER_H__ +#define __AUDIT_LOGGER_H__ + +#include +#include +#include +#include +#include + +#include "logsink.h" + +namespace audit { + +enum class LogLevel : int { + Error, + Warning, + Debug, + Info, + Trace +}; + +class Logger { +public: + static void setLogLevel(const LogLevel level); + static LogLevel getLogLevel(void); + static void log(LogLevel severity, + const std::string& file, + const unsigned int line, + const std::string& func, + const std::string& message); + +private: + static LogLevel logLevel; + static std::unique_ptr backend; +}; + +#ifndef __FILENAME__ +#define __FILENAME__ \ +(::strrchr(__FILE__, '/') ? ::strrchr(__FILE__, '/') + 1 : __FILE__) +#endif + +#define LOG(SEVERITY, MESSAGE) \ +do { \ + if (audit::LogLevel::SEVERITY <= audit::Logger::getLogLevel()) { \ + audit::Logger::log(audit::LogLevel::SEVERITY, \ + __FILENAME__, __LINE__, __func__, MESSAGE); \ + } \ +} while (0) + +#define ERROR(MESSAGE) LOG(Error, MESSAGE) +#define WARN(MESSAGE) LOG(Warning, MESSAGE) + +#if !defined(NDEBUG) +#define INFO(MESSAGE) LOG(Info, MESSAGE) +#define DEBUG(MESSAGE) LOG(Debug, MESSAGE) +#define TRACE(MESSAGE) LOG(Trace, MESSAGE) +#else +#define INFO(MESSAGE) do {} while (0) +#define DEBUG(MESSAGE) do {} while (0) +#define TRACE(MESSAGE) do {} while (0) +#endif //NDEBUG + +std::string LogLevelToString(const LogLevel level); + +} // namespace audit +#endif //__AUDIT_LOGGER_H__ diff --git a/common/audit/logsink.h b/common/audit/logsink.h new file mode 100644 index 0000000..f1949df --- /dev/null +++ b/common/audit/logsink.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __AUDIT_LOGSINK_H__ +#define __AUDIT_LOGSINK_H__ + +#include + +namespace audit { + +class LogSink { +public: + LogSink() {} + virtual ~LogSink() {} + virtual void sink(const std::string& message) = 0; +}; + +} // namespace audit +#endif //__AUDIT_LOGSINK_H__ diff --git a/common/audit/null-sink.cpp b/common/audit/null-sink.cpp new file mode 100644 index 0000000..ec335a0 --- /dev/null +++ b/common/audit/null-sink.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "null-sink.h" + +namespace audit { + +void NullLogSink::sink(const std::string& message) +{ +}; + +} // namespace audit diff --git a/common/audit/null-sink.h b/common/audit/null-sink.h new file mode 100644 index 0000000..cd5d9dc --- /dev/null +++ b/common/audit/null-sink.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __AUDIT_NULL_LOGSINK_H__ +#define __AUDIT_NULL_LOGSINK_H__ + +#include + +#include "logsink.h" + +namespace audit { + +class NullLogSink : public LogSink { +public: + void sink(const std::string& message) override; +}; + +} // namespace audit +#endif //__AUDIT_NULL_LOGSINK_H__ diff --git a/common/auth/group.cpp b/common/auth/group.cpp new file mode 100644 index 0000000..89e1ceb --- /dev/null +++ b/common/auth/group.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include + +#include +#include + +#include "group.h" +#include "shadow.h" +#include "exception.h" + +namespace runtime { + +Group::Group(const Group& group) : + name(group.name), gid(group.gid) +{ +} + +Group::Group(const std::string& group) +{ + struct group grp, *result; + int bufsize; + + bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); + if (bufsize == -1) + bufsize = 16384; + + std::unique_ptr buf(new char[bufsize]); + + ::getgrnam_r(group.c_str(), &grp, buf.get(), bufsize, &result); + if (result == NULL) { + throw runtime::Exception("Group doesn't exist"); + } + + name = result->gr_name; + gid = result->gr_gid; +} + +Group::Group(const gid_t group) +{ + struct group grp, *result; + int bufsize; + + bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); + if (bufsize == -1) + bufsize = 16384; + + std::unique_ptr buf(new char[bufsize]); + + ::getgrgid_r(group, &grp, buf.get(), bufsize, &result); + if (result == NULL) { + throw runtime::Exception("Group doesn't exist"); + } + + name = result->gr_name; + gid = result->gr_gid; +} + +Group::Group() : + Group(::getgid()) +{ +} + +} // namespace Shadow diff --git a/common/auth/group.h b/common/auth/group.h new file mode 100644 index 0000000..5c0b583 --- /dev/null +++ b/common/auth/group.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_GROUP_H__ +#define __RUNTIME_GROUP_H__ + +#include +#include + +#include + +#ifndef INVALID_GID +#define INVALID_GID UINT_MAX +#endif + +namespace runtime { + +class Group final { +public: + Group(const std::string& name); + Group(const gid_t group); + Group(const Group& group); + Group(); + + const std::string& getName() const + { + return name; + } + + const gid_t getGid() const + { + return gid; + } + +private: + std::string name; + gid_t gid; +}; + +} // namespace runtime + +#endif //__RUNTIME_GROUP_H__ diff --git a/common/auth/user.cpp b/common/auth/user.cpp new file mode 100644 index 0000000..0848a5e --- /dev/null +++ b/common/auth/user.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include + +#include +#include + +#include "user.h" +#include "group.h" +#include "shadow.h" +#include "filesystem.h" +#include "exception.h" + +namespace runtime { + +User::User(const User& user) : + name(user.name), uid(user.uid), gid(user.gid) +{ +} + +User::User(const std::string& user) +{ + struct passwd pwd, *result; + int bufsize; + + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize == -1) + bufsize = 16384; + + std::unique_ptr buf(new char[bufsize]); + + ::getpwnam_r(user.c_str(), &pwd, buf.get(), bufsize, &result); + if (result == NULL) { + throw runtime::Exception("User " + user + " doesn't exist"); + } + + name = result->pw_name; + uid = result->pw_uid; + gid = result->pw_gid; +} + +User::User(const uid_t user) +{ + struct passwd pwd, *result; + int bufsize; + + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize == -1) + bufsize = 16384; + + std::unique_ptr buf(new char[bufsize]); + ::getpwuid_r(user, &pwd, buf.get(), bufsize, &result); + if (result == NULL) { + throw runtime::Exception("User " + std::to_string(user) + "doesn't exist"); + } + + name = result->pw_name; + uid = result->pw_uid; + gid = result->pw_gid; +} + +User::User() : + User(::getuid()) +{ +} + +} // namespace runtime diff --git a/common/auth/user.h b/common/auth/user.h new file mode 100644 index 0000000..88aa5b0 --- /dev/null +++ b/common/auth/user.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_USER_H__ +#define __RUNTIME_USER_H__ + +#include +#include + +#include + +#ifndef INVALID_UID +#define INVALID_UID UINT_MAX +#endif + +namespace runtime { + +class User final { +public: + User(const std::string& name); + User(const uid_t user); + User(const User& user); + User(); + + const std::string& getName() const + { + return name; + } + + uid_t getUid() const + { + return uid; + } + + gid_t getGid() const + { + return gid; + } + +private: + std::string name; + uid_t uid; + gid_t gid; +}; + +} // namespace runtime + +#endif //__RUNTIME_USER_H__ diff --git a/common/data-type.h b/common/data-type.h new file mode 100644 index 0000000..b5b232c --- /dev/null +++ b/common/data-type.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_DATA_TYPE_H__ +#define __RUNTIME_DATA_TYPE_H__ +#include +#include +#include + +#include "reflection.h" + +struct Void { + NO_REFLECTABLE_PROPERTY +}; + +struct String { + String() = default; + String(const String& str) : value(str.value) {} + String(String&& str) : value(std::move(str.value)) {} + + String(const char* str) : value(str) {} + String(const std::string& str) : value(str) {} + + String& operator=(const String& str) + { + if (this != &str) { + value = str.value; + } + + return *this; + } + + String& operator=(String&& str) + { + if (this != &str) { + value = std::move(str.value); + } + return *this; + } + + std::string value; + REFLECTABLE(value) +}; + +struct StringPair { + std::string first; + std::string second; + REFLECTABLE(first, second) +}; + +struct Status { + Status() : code(0) {} + Status(int v) : code(v) {} + + operator int() const + { + return code; + } + + int code; + REFLECTABLE(code) +}; + +template +struct Vector { + std::vector value; + REFLECTABLE(value) +}; + +#endif //!__RUNTIME_DATA_TYPE_H__ diff --git a/common/db/column.cpp b/common/db/column.cpp new file mode 100644 index 0000000..3a57600 --- /dev/null +++ b/common/db/column.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +#include "column.h" + +namespace database { + +Column::Column(const Statement& stmt, int idx) : + statement(stmt.get()), + index(idx) +{ +} + +Column::~Column() noexcept +{ +} + +std::string Column::getName() const +{ + return sqlite3_column_name(statement, index); +} + +int Column::getInt() const +{ + return sqlite3_column_int(statement, index); +} + +sqlite3_int64 Column::getInt64() const +{ + return sqlite3_column_int64(statement, index); +} + +double Column::getDouble() const +{ + return sqlite3_column_double(statement, index); +} + +const char* Column::getText() const +{ + return reinterpret_cast(sqlite3_column_text(statement, index)); +} + +const void* Column::getBlob() const +{ + return sqlite3_column_blob(statement, index); +} + +int Column::getType() const +{ + return sqlite3_column_type(statement, index); +} + +int Column::getBytes() const +{ + return sqlite3_column_bytes(statement, index); +} + +} // namespace database diff --git a/common/db/column.h b/common/db/column.h new file mode 100644 index 0000000..1dc9965 --- /dev/null +++ b/common/db/column.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __DATABASE_COLUMN_H__ +#define __DATABASE_COLUMN_H__ + +#include + +#include + +#include "statement.h" + +namespace database { + +class Column { +public: + Column(const Statement& stmt, int idx); + virtual ~Column() noexcept; + + std::string getName() const; + sqlite3_int64 getInt64() const; + const char* getText() const; + double getDouble() const; + const void* getBlob() const; + int getInt() const; + int getType() const; + int getBytes() const; + + inline int size() const + { + return getBytes(); + } + + inline operator int() const + { + return getInt(); + } + + inline operator sqlite3_int64() const + { + return getInt64(); + } + + inline operator double() const + { + return getDouble(); + } + + inline operator const char*() const + { + return getText(); + } + + inline operator const void*() const + { + return getBlob(); + } + +private: + sqlite3_stmt* statement; + int index; +}; + +} // namespace database + +#endif //__DATABASE_COLUMN_H__ diff --git a/common/db/connection.cpp b/common/db/connection.cpp new file mode 100644 index 0000000..5ea016e --- /dev/null +++ b/common/db/connection.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +#include "exception.h" + +#include "connection.h" + +namespace database { + +Connection::Connection(const std::string& name, const int flags) : + handle(nullptr), filename(name) +{ + if (::sqlite3_open_v2(filename.c_str(), &handle, flags, NULL)) { + throw runtime::Exception(getErrorMessage()); + } +} + +Connection::~Connection() +{ + ::sqlite3_close(handle); +} + +int Connection::exec(const std::string& query) +{ + if (::sqlite3_exec(handle, query.c_str(), NULL, NULL, NULL) != SQLITE_OK) { + throw runtime::Exception(getErrorMessage()); + } + + return ::sqlite3_changes(handle); +} + +} // namespace database diff --git a/common/db/connection.h b/common/db/connection.h new file mode 100644 index 0000000..1465533 --- /dev/null +++ b/common/db/connection.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __DATABASE_CONNECTION_H__ +#define __DATABASE_CONNECTION_H__ + +#include + +#include + +namespace database { + +class Connection { +public: + enum Mode { + Create = SQLITE_OPEN_CREATE, + ReadWrite = SQLITE_OPEN_READWRITE + }; + + Connection(const std::string& name, const int flags); + ~Connection(); + + int exec(const std::string& query); + bool isTableExists(const std::string& tableName); + + inline long long getLastInsertRowId() const noexcept + { + return sqlite3_last_insert_rowid(handle); + } + + inline const std::string& getName() const noexcept + { + return filename; + } + + inline int getErrorCode() const + { + return sqlite3_errcode(handle); + } + + inline int getExtendedErrorCode() const + { + return sqlite3_extended_errcode(handle); + } + + inline std::string getErrorMessage() const + { + return sqlite3_errmsg(handle); + } + + inline sqlite3* get() const noexcept + { + return handle; + } + +private: + sqlite3* handle; + std::string filename; +}; + +} // namespace database +#endif //__DATABASE_CONNECTION_H__ diff --git a/common/db/statement.cpp b/common/db/statement.cpp new file mode 100644 index 0000000..22d2243 --- /dev/null +++ b/common/db/statement.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include + +#include "connection.h" +#include "statement.h" +#include "column.h" + +#include "exception.h" + +namespace database { + +Statement::Statement(const Connection& db, const std::string& query) : + statement(nullptr), + columnCount(0), + validRow(false) +{ + if (SQLITE_OK != ::sqlite3_prepare_v2(db.get(), + query.c_str(), + query.size(), + &statement, + NULL)) { + throw runtime::Exception(db.getErrorMessage()); + } + + columnCount = sqlite3_column_count(statement); +} + +Statement::~Statement() +{ + ::sqlite3_finalize(statement); +} + +void Statement::reset() +{ + if (::sqlite3_reset(statement) != SQLITE_OK) { + throw runtime::Exception(getErrorMessage()); + } +} + +void Statement::clearBindings() +{ + if (::sqlite3_clear_bindings(statement) != SQLITE_OK) { + throw runtime::Exception(getErrorMessage()); + } +} + +std::string Statement::getErrorMessage() const +{ + return ::sqlite3_errmsg(::sqlite3_db_handle(statement)); +} + +std::string Statement::getErrorMessage(int errorCode) const +{ + return ::sqlite3_errstr(errorCode); +} + +bool Statement::step() +{ + if (SQLITE_ROW == ::sqlite3_step(statement)) { + return (validRow = true); + } + + return (validRow = false); +} + +int Statement::exec() +{ + if (SQLITE_DONE == ::sqlite3_step(statement)) { + validRow = false; + } + + return sqlite3_changes(sqlite3_db_handle(statement)); +} + +Column Statement::getColumn(const int index) +{ + if (!validRow || (index >= columnCount)) { + throw runtime::Exception(getErrorMessage(SQLITE_RANGE)); + } + + return Column(*this, index); +} + +bool Statement::isNullColumn(const int index) const +{ + if (!validRow || (index >= columnCount)) { + throw runtime::Exception(getErrorMessage(SQLITE_RANGE)); + } + + return (SQLITE_NULL == sqlite3_column_type(statement, index)); +} + +std::string Statement::getColumnName(const int index) const +{ + if (index >= columnCount) { + throw runtime::Exception(getErrorMessage(SQLITE_RANGE)); + } + + return sqlite3_column_name(statement, index); +} + + +void Statement::bind(const int index, const int& value) +{ + if (SQLITE_OK != ::sqlite3_bind_int(statement, index, value)) { + throw runtime::Exception(getErrorMessage()); + } +} + +void Statement::bind(const int index, const sqlite3_int64& value) +{ + if (SQLITE_OK != ::sqlite3_bind_int64(statement, index, value)) { + throw runtime::Exception(getErrorMessage()); + } +} + +void Statement::bind(const int index, const double& value) +{ + if (SQLITE_OK != ::sqlite3_bind_double(statement, index, value)) { + throw runtime::Exception(getErrorMessage()); + } +} + +void Statement::bind(const int index, const char* value) +{ + if (SQLITE_OK != ::sqlite3_bind_text(statement, index, value, -1, SQLITE_TRANSIENT)) { + throw runtime::Exception(getErrorMessage()); + } +} + +void Statement::bind(const int index, const std::string& value) +{ + if (SQLITE_OK != ::sqlite3_bind_text(statement, index, value.c_str(), + static_cast(value.size()), SQLITE_TRANSIENT)) { + throw runtime::Exception(getErrorMessage()); + } +} + +void Statement::bind(const int index, const void* value, const int size) +{ + if (SQLITE_OK != ::sqlite3_bind_blob(statement, index, value, size, SQLITE_TRANSIENT)) { + throw runtime::Exception(getErrorMessage()); + } +} + +void Statement::bind(const int index) +{ + if (SQLITE_OK != ::sqlite3_bind_null(statement, index)) { + throw runtime::Exception(getErrorMessage()); + } +} + +void Statement::bind(const std::string& name, const int& value) +{ + int index = sqlite3_bind_parameter_index(statement, name.c_str()); + if (SQLITE_OK != sqlite3_bind_int(statement, index, value)) { + throw runtime::Exception(getErrorMessage()); + } +} + +void Statement::bind(const std::string& name, const sqlite3_int64& value) +{ + int index = sqlite3_bind_parameter_index(statement, name.c_str()); + if (SQLITE_OK != ::sqlite3_bind_int64(statement, index, value)) { + throw runtime::Exception(getErrorMessage()); + } +} + +void Statement::bind(const std::string& name, const double& value) +{ + int index = sqlite3_bind_parameter_index(statement, name.c_str()); + if (SQLITE_OK != ::sqlite3_bind_double(statement, index, value)) { + throw runtime::Exception(getErrorMessage()); + } +} + +void Statement::bind(const std::string& name, const std::string& value) +{ + int index = sqlite3_bind_parameter_index(statement, name.c_str()); + if (SQLITE_OK != ::sqlite3_bind_text(statement, index, value.c_str(), + static_cast(value.size()), SQLITE_TRANSIENT)) { + throw runtime::Exception(getErrorMessage()); + } +} + +void Statement::bind(const std::string& name, const char* value) +{ + int index = sqlite3_bind_parameter_index(statement, name.c_str()); + if (SQLITE_OK != ::sqlite3_bind_text(statement, index, value, -1, SQLITE_TRANSIENT)) { + throw runtime::Exception(getErrorMessage()); + } +} + +void Statement::bind(const std::string& name, const void* value, const int size) +{ + int index = sqlite3_bind_parameter_index(statement, name.c_str()); + if (SQLITE_OK != ::sqlite3_bind_blob(statement, index, value, size, SQLITE_TRANSIENT)) { + throw runtime::Exception(getErrorMessage()); + } +} + +void Statement::bind(const std::string& name) +{ + int index = sqlite3_bind_parameter_index(statement, name.c_str()); + if (SQLITE_OK != ::sqlite3_bind_null(statement, index)) { + throw runtime::Exception(getErrorMessage()); + } +} + +} // namespace database diff --git a/common/db/statement.h b/common/db/statement.h new file mode 100644 index 0000000..c834303 --- /dev/null +++ b/common/db/statement.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __DATABASE_STATEMENT_H__ +#define __DATABASE_STATEMENT_H__ + +#include +#include + +#include + +namespace database { + +class Column; +class Connection; + +class Statement { +public: + Statement(const Connection& db, const std::string& query); + virtual ~Statement(); + + int exec(); + bool step(); + + void reset(); + void clearBindings(); + std::string getErrorMessage() const; + std::string getErrorMessage(int errorCode) const; + + Column getColumn(const int index); + std::string getColumnName(const int index) const; + bool isNullColumn(const int index) const; + + void bind(const int index, const int& value); + void bind(const int index, const sqlite3_int64& value); + void bind(const int index, const double& value); + void bind(const int index, const std::string& value); + void bind(const int index, const char* value); + void bind(const int index, const void* value, const int size); + void bind(const int index); + + void bind(const std::string& name, const int& value); + void bind(const std::string& name, const sqlite3_int64& value); + void bind(const std::string& name, const double& value); + void bind(const std::string& name, const std::string& value); + void bind(const std::string& name, const char* value); + void bind(const std::string& name, const void* value, const int size); + void bind(const std::string& name); + + inline int getColumnCount() const + { + return columnCount; + } + + inline sqlite3_stmt* get() const noexcept + { + return statement; + } + +private: + typedef std::map ColumnMap; + + sqlite3_stmt* statement; + int columnCount; + int validRow; + ColumnMap columnNames; +}; + +} // namespace database + +#endif //__DATABASE_STATEMENT_H__ diff --git a/common/dbus/connection.cpp b/common/dbus/connection.cpp new file mode 100644 index 0000000..e85310d --- /dev/null +++ b/common/dbus/connection.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "connection.h" + +#include "exception.h" +#include "dbus/error.h" +#include "dbus/variant.h" +#include "dbus/connection.h" +#include "audit/logger.h" + +namespace dbus { + +namespace { + +const std::string DBUS_SYSTEM_BUS_ADDRESS = "kernel:path=/sys/fs/kdbus/0-system/bus;unix:path=/var/run/dbus/system_bus_socket"; + +void defaultCallback(GDBusConnection* connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { + Connection::signalCallback* func = reinterpret_cast (user_data); + (*func)(Variant(parameters)); + delete func; +} + +} // namespace + +Connection::Connection(const std::string& address) : + connection(nullptr) +{ + Error error; + const GDBusConnectionFlags flags = static_cast + (G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION); + + connection = g_dbus_connection_new_for_address_sync(address.c_str(), flags, NULL, NULL, &error); + if (error) { + ERROR(error->message); + throw runtime::Exception(error->message); + } +} + +Connection::~Connection() +{ + if (connection) { + g_dbus_connection_close_sync(connection, NULL, NULL); + g_object_unref(connection); + } +} + +Connection& Connection::getSystem() +{ + static Connection __instance__(DBUS_SYSTEM_BUS_ADDRESS); + return __instance__; +} + +Connection::subscriptionId Connection::subscribeSignal(const std::string& sender, + const std::string& interface, + const std::string& object, + const std::string& member, + const signalCallback callback) +{ + subscriptionId id; + id = g_dbus_connection_signal_subscribe(connection, + sender.empty() ? NULL : sender.c_str(), + interface.empty() ? NULL : interface.c_str(), + object.empty() ? NULL : object.c_str(), + member.empty() ? NULL : member.c_str(), + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + defaultCallback, + new signalCallback(callback), + NULL); + return id; +} + +void Connection::unsubscribeSignal(Connection::subscriptionId id) +{ + g_dbus_connection_signal_unsubscribe(connection, id); +} + +const Variant Connection::methodcall(const std::string& busName, + const std::string& object, + const std::string& interface, + const std::string& method, + int timeout, + const std::string& replyType, + const std::string& paramType, + ...) +{ + Variant result; + Error error; + va_list ap; + + va_start(ap, paramType); + result = g_dbus_connection_call_sync(connection, + busName.empty() ? NULL : + busName.c_str(), + object.c_str(), + interface.c_str(), + method.c_str(), + paramType.empty() ? NULL : + g_variant_new_va(paramType.c_str(), NULL, &ap), + replyType.empty() ? NULL : + G_VARIANT_TYPE(replyType.c_str()), + G_DBUS_CALL_FLAGS_NONE, + timeout, + NULL, + &error); + va_end(ap); + + if (error) { + ERROR(error->message); + throw runtime::Exception(error->message); + } + + return result; +} + +} // namespace dbus diff --git a/common/dbus/connection.h b/common/dbus/connection.h new file mode 100644 index 0000000..451b700 --- /dev/null +++ b/common/dbus/connection.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_DBUS_CONNECTION_H__ + #define __RUNTIME_DBUS_CONNECTION_H__ + +#include +#include + +#include + +#include "dbus/variant.h" + +namespace dbus { + +class Connection { +public: + typedef unsigned int subscriptionId; + typedef std::function signalCallback; + + Connection() = delete; + Connection(const Connection&) = delete; + ~Connection(); + + Connection& operator=(const Connection&) = delete; + + static Connection& getSystem(); + + subscriptionId subscribeSignal(const std::string& sender, + const std::string& interface, + const std::string& object, + const std::string& member, + const signalCallback callback); + + + void unsubscribeSignal(subscriptionId id); + + const Variant methodcall(const std::string& busName, + const std::string& object, + const std::string& interface, + const std::string& method, + int timeout, + const std::string& replyType, + const std::string& paramType, + ...); + +private: + Connection(const std::string& address); + + GDBusConnection* connection; +}; + +} // namespace dbus + + #endif //! __RUNTIME_DBUS_CONNECTION_H__ diff --git a/common/dbus/error.cpp b/common/dbus/error.cpp new file mode 100644 index 0000000..07a64f6 --- /dev/null +++ b/common/dbus/error.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "dbus/error.h" + +namespace dbus { + +Error::Error() : + error(nullptr) +{ +} + +Error::~Error() +{ + if (error) { + g_error_free(error); + } +} + +GError** Error::operator& () +{ + return &error; +} + +const GError* Error::operator-> () const +{ + return error; +} + +Error::operator bool () const +{ + return error != nullptr; +} + +} // namespace dbus diff --git a/common/dbus/error.h b/common/dbus/error.h new file mode 100644 index 0000000..d48c611 --- /dev/null +++ b/common/dbus/error.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_DBUS_ERROR_H__ +#define __RUNTIME_DBUS_ERROR_H__ + +#include +#include + +namespace dbus { + +class Error { +public: + Error(); + ~Error(); + + GError** operator& (); + const GError* operator-> () const; + operator bool () const; + +private: + GError* error; +}; + +} // namespace dbus + +#endif //!__RUNTIME_DBUS_ERROR_H__ diff --git a/common/dbus/variant.cpp b/common/dbus/variant.cpp new file mode 100644 index 0000000..524a25f --- /dev/null +++ b/common/dbus/variant.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "dbus/variant.h" + +namespace dbus { + +Variant::Variant(GVariant* var) : + variant(var) +{ +} + +Variant::Variant(Variant&& var) : + variant(var.variant) +{ + var.variant = nullptr; +} + +Variant::Variant() : + variant(nullptr) +{ +} + +Variant::~Variant() +{ + if (variant) { + g_variant_unref(variant); + } +} + +Variant& Variant::operator=(GVariant* var) +{ + variant = var; + return *this; +} + +Variant::operator bool () const +{ + return variant != nullptr; +} + +void Variant::get(const std::string& format, ...) const +{ + va_list ap; + + va_start(ap, format); + g_variant_get_va(variant, format.c_str(), NULL, &ap); + va_end(ap); +} + + +VariantIterator::VariantIterator(GVariantIter* it) : + iterator(it) +{ +} + +VariantIterator::VariantIterator(VariantIterator&& it) : + iterator(it.iterator) +{ + it.iterator = nullptr; +} + +VariantIterator::VariantIterator() : + iterator(nullptr) +{ +} + +VariantIterator::~VariantIterator() +{ + if (iterator) { + g_variant_iter_free(iterator); + } +} + +VariantIterator& VariantIterator::operator=(GVariantIter* it) +{ + iterator = it; + return *this; +} + +VariantIterator::operator bool () const +{ + return iterator != nullptr; +} + +GVariantIter** VariantIterator::operator & () +{ + return &iterator; +} + +bool VariantIterator::get(const std::string& format, ...) const +{ + GVariant *var; + va_list ap; + var = g_variant_iter_next_value(iterator); + if (var == NULL) { + return false; + } + + va_start(ap, format); + g_variant_get_va(var, format.c_str(), NULL, &ap); + va_end(ap); + + g_variant_unref(var); + + return true; +} + +} // namespace dbus diff --git a/common/dbus/variant.h b/common/dbus/variant.h new file mode 100644 index 0000000..9b4348b --- /dev/null +++ b/common/dbus/variant.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_DBUS_VARIANT_H__ +#define __RUNTIME_DBUS_VARIANT_H__ + +#include +#include + +namespace dbus { + +class Variant { +public: + Variant(GVariant* var); + Variant(Variant&& var); + Variant(); + ~Variant(); + + Variant& operator=(GVariant* var); + operator bool () const; + GVariant* operator & (); + + void get(const std::string& format, ...) const; +private: + GVariant* variant; +}; + +class VariantIterator { +public: + VariantIterator(GVariantIter* it); + VariantIterator(VariantIterator&& it); + VariantIterator(); + ~VariantIterator(); + + VariantIterator& operator=(GVariantIter* it); + operator bool () const; + GVariantIter** operator & (); + + bool get(const std::string& format, ...) const; +private: + GVariantIter* iterator; +}; + + +} // namespace dbus + +#endif //!__RUNTIME_DBUS_VARIANT_H__ diff --git a/common/error.cpp b/common/error.cpp new file mode 100644 index 0000000..839d3ca --- /dev/null +++ b/common/error.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include + +#include "error.h" + +namespace runtime { + +int Error::lastErrorCode() +{ + return errno; +} + +std::string Error::message(int errorCode) +{ + char errmsg[256]; + return ::strerror_r(errorCode, errmsg, sizeof(errmsg)); +} + +std::string Error::message() +{ + return message(lastErrorCode()); +} + +std::string GetSystemErrorMessage(int errorCode) +{ + return Error::message(errorCode); +} + +std::string GetSystemErrorMessage() +{ + return Error::message(); +} + +} // namespace runtime diff --git a/common/error.h b/common/error.h new file mode 100644 index 0000000..f746c38 --- /dev/null +++ b/common/error.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_ERROR_H__ +#define __RUNTIME_ERROR_H__ + +#include + +namespace runtime { + +class Error { +public: + static std::string message(); + static std::string message(int errorCode); + static int lastErrorCode(); +}; + +std::string GetSystemErrorMessage(); +std::string GetSystemErrorMessage(int errorCode); + +} // namespace runtime +#endif //__RUNTIME_ERROR_H__ diff --git a/common/eventfd.cpp b/common/eventfd.cpp new file mode 100644 index 0000000..a2943f3 --- /dev/null +++ b/common/eventfd.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include + +#include + +#include "eventfd.h" +#include "error.h" +#include "exception.h" + +namespace runtime { + +EventFD::EventFD(unsigned int initval, int flags) +{ + fd = ::eventfd(initval, flags); + if (fd == -1) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } +} + +EventFD::~EventFD() +{ + if (fd != -1) { + ::close(fd); + } +} + +void EventFD::close() +{ + ::close(fd); +} + +void EventFD::send() +{ + const std::uint64_t val = 1; + if (::write(fd, &val, sizeof(val)) == -1) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } +} + +void EventFD::receive() +{ + std::uint64_t val; + if (::read(fd, &val, sizeof(val)) == -1) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } +} + +} // namespace runtime diff --git a/common/eventfd.h b/common/eventfd.h new file mode 100644 index 0000000..a642136 --- /dev/null +++ b/common/eventfd.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_EVENTFD_H__ +#define __RUNTIME_EVENTFD_H__ + +#include + +namespace runtime { + +class EventFD { +public: + EventFD(unsigned int initval = 0, int flags = EFD_SEMAPHORE | EFD_CLOEXEC); + ~EventFD(); + + EventFD(const EventFD&) = delete; + EventFD& operator=(const EventFD&) = delete; + + void send(); + void receive(); + void close(); + + int getFd() const + { + return fd; + } + +private: + int fd; +}; + +} // namespace runtime + +#endif //__RUNTIME_EVENTFD_H__ diff --git a/common/exception.h b/common/exception.h new file mode 100644 index 0000000..734019a --- /dev/null +++ b/common/exception.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_EXCEPTION_H__ +#define __RUNTIME_EXCEPTION_H__ + +#include +#include + +namespace runtime { + +class Exception: public std::runtime_error { +public: + Exception(const std::string& error) : + std::runtime_error(error) + { + } +}; +} // namespace runtime +#endif //__RUNTIME_EXCEPTION_H__ diff --git a/common/file-descriptor.h b/common/file-descriptor.h new file mode 100644 index 0000000..d032c05 --- /dev/null +++ b/common/file-descriptor.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_FILE_DESCRIPTOR_H__ +#define __RUNTIME_FILE_DESCRIPTOR_H__ + +#include + +#include + +struct FileDescriptor { + FileDescriptor(int fd = -1, bool autoclose = false) : + fileDescriptor(fd), autoClose(autoclose) + { + } + + FileDescriptor(const FileDescriptor&) = delete; + FileDescriptor(FileDescriptor&& rhs) : + fileDescriptor(rhs.fileDescriptor), + autoClose(rhs.autoClose) + { + rhs.fileDescriptor = -1; + } + + ~FileDescriptor() { + if ((fileDescriptor != -1) && (autoClose == true)) { + ::close(fileDescriptor); + } + } + + FileDescriptor& operator=(const int fd) { + fileDescriptor = fd; + autoClose = false; + return *this; + } + + FileDescriptor& operator=(FileDescriptor&& rhs) { + if (this != &rhs) { + fileDescriptor = rhs.fileDescriptor; + autoClose = rhs.autoClose; + rhs.fileDescriptor = -1; + } + + return *this; + } + + int fileDescriptor; + bool autoClose; +}; + +#endif //__RUNTIME_FILE_DESCRIPTOR_H__ diff --git a/common/filesystem.cpp b/common/filesystem.cpp new file mode 100755 index 0000000..0897500 --- /dev/null +++ b/common/filesystem.cpp @@ -0,0 +1,544 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "filesystem.h" +#include "error.h" +#include "exception.h" + +namespace runtime { + +File::File() : + descriptor(-1) +{ +} + +File::File(const char* pathname) : + descriptor(-1), path(pathname) +{ +} + +File::File(const std::string& pathname) : + descriptor(-1), path(pathname) +{ +} + +File::File(const File& file) : + File(file.getPath()) +{ +} + +File::File(const std::string& pathname, int flags) : + File(pathname) +{ + open(flags); +} + +File::~File() +{ + close(); +} + +bool File::exists() const +{ + struct stat st; + return (::stat(path.c_str(), &st) == 0); +} + +bool File::canRead() const +{ + if (::access(path.c_str(), R_OK) == 0) { + return true; + } + + return false; +} + +bool File::canWrite() const +{ + if (::access(path.c_str(), W_OK) == 0) { + return true; + } + + return false; +} + +bool File::canExecute() const +{ + if (::access(path.c_str(), X_OK) == 0) { + return true; + } + + return false; +} + +bool File::isLink() const +{ + struct stat st; + if (::lstat(path.c_str(), &st) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + + return S_ISLNK(st.st_mode); +} + +bool File::isFile() const +{ + struct stat st; + if (::stat(path.c_str(), &st) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + + return S_ISREG(st.st_mode); +} + +bool File::isDirectory() const +{ + struct stat st; + if (::stat(path.c_str(), &st) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + + return S_ISDIR(st.st_mode); +} + +bool File::isDevice() const +{ + struct stat st; + if (::stat(path.c_str(), &st) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + + return (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)); +} + +mode_t File::getMode() const +{ + struct stat st; + if (::stat(path.c_str(), &st) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + + return st.st_mode; +} + +uid_t File::getUid() const +{ + struct stat st; + if (::stat(path.c_str(), &st) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + + return st.st_uid; +} + +gid_t File::getGid() const +{ + struct stat st; + if (::stat(path.c_str(), &st) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + + return st.st_gid; +} + +size_t File::size() const +{ + struct stat st; + if (::stat(path.c_str(), &st) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + + return st.st_size; +} + +void File::create(mode_t mode) +{ + while (1) { + descriptor = ::creat(path.c_str(), mode); + if (descriptor == -1) { + if (errno != EINTR) { + continue; + } + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + return; + } +} + +void File::open(int flags) +{ + while (1) { + descriptor = ::open(path.c_str(), flags); + if (descriptor == -1) { + if (errno != EINTR) { + continue; + } + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + return; + } +} + +void File::close() +{ + if (descriptor != -1) { + while ((::close(descriptor) == -1) && (errno == EINTR)); + descriptor = -1; + } +} + +void File::read(void *buffer, const size_t size) const +{ + size_t total = 0; + + while (total < size) { + int bytes = ::read(descriptor, reinterpret_cast(buffer) + total, size - total); + if (bytes >= 0) { + total += bytes; + } else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + continue; + } else { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + } +} + +void File::write(const void *buffer, const size_t size) const +{ + size_t written = 0; + + while (written < size) { + int bytes = ::write(descriptor, reinterpret_cast(buffer) + written, size - written); + if (bytes >= 0) { + written += bytes; + } else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + continue; + } else { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + } +} + +File File::copyTo(const std::string& destDir) +{ + const std::string& filename = getPath(); + File destFile(destDir); + if (destFile.exists()) { + destFile = destDir + "/" + getName(); + } + + if (isDirectory()) { + DirectoryIterator iter(filename), end; + destFile.makeDirectory(false, getUid(), getGid()); + + while (iter != end) { + iter->copyTo(destFile.getPath()); + ++iter; + } + } else { + open(O_RDONLY); + destFile.create(getMode()); + ::sendfile(destFile.descriptor, descriptor, 0, size()); + destFile.close(); + close(); + } + + return destFile; +} + +void File::remove(bool recursive) +{ + if (isDirectory()) { + if (recursive) { + DirectoryIterator iter(path), end; + while (iter != end) { + iter->remove(true); + ++iter; + } + } + if (::rmdir(path.c_str()) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + } else { + if (::unlink(path.c_str()) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + } +} + +void File::makeBaseDirectory(uid_t uid, gid_t gid) +{ + std::string::size_type i = path[0] != '/' ? -1 : 0; + const std::string& pathStr = path; + while ((i = pathStr.find('/', i + 1)) != std::string::npos) { + std::string substr = pathStr.substr(0, i); + int ret = ::mkdir(substr.c_str(), 0777); + if ((ret == -1) && (errno == EEXIST)) { + continue; + } else if (ret == 0) { + if ((uid | gid) != 0) { + if (::chown(substr.c_str(), uid, gid) == -1) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + } + } else { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + } +} + +void File::makeDirectory(bool recursive, uid_t uid, gid_t gid) +{ + if (recursive) { + makeBaseDirectory(uid, gid); + } + + if (::mkdir(path.c_str(), 0777) == -1) { + throw runtime::Exception("mkdir failed in makeDirectory: " + path); + } + + if ((uid | gid) != 0) { + chown(uid, gid); + } +} + +void File::chown(uid_t uid, gid_t gid, bool recursive) +{ + if (::chown(path.c_str(), uid, gid) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + + if (recursive && isDirectory()) { + DirectoryIterator iter(path), end; + while (iter != end) { + iter->chown(uid, gid, true); + ++iter; + } + } +} + +void File::chmod(mode_t mode, bool recursive) +{ + if (::chmod(path.c_str(), mode) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + + if (recursive && isDirectory()) { + DirectoryIterator iter(path), end; + while (iter != end) { + iter->chmod(mode, true); + ++iter; + } + } +} + +void File::lock() const +{ + if (::flock(descriptor, LOCK_EX) == -1) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } +} + +void File::unlock() const +{ + if (::flock(descriptor, LOCK_UN) == -1) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } +} + +DirectoryIterator::DirectoryIterator() + : directoryHandle(nullptr) +{ +} + +DirectoryIterator::DirectoryIterator(const std::string& dir) + : directoryHandle(nullptr) +{ + reset(dir); +} + +DirectoryIterator::~DirectoryIterator() +{ + if (directoryHandle != nullptr) { + ::closedir(directoryHandle); + } +} + +void DirectoryIterator::reset(const std::string& dir) +{ + if (directoryHandle != nullptr) { + ::closedir(directoryHandle); + directoryHandle = nullptr; + } + + basename = dir; + directoryHandle = ::opendir(basename.c_str()); + if (directoryHandle == nullptr) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + + next(); +} + +void DirectoryIterator::next() +{ + std::string name; + struct dirent entry, *ent; + + while (1) { + if (readdir_r(directoryHandle, &entry, &ent) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + + if (ent == NULL) + break; + + if (ent->d_name[0] == '.' && ent->d_name[1] == '\0') { + continue; + } + + if (ent->d_name[0] == '.' && + ent->d_name[1] == '.' && ent->d_name[2] == '\0') { + continue; + } + + name = basename + "/" + std::string(ent->d_name); + break; + } + + current = name; +} + +DirectoryIterator& DirectoryIterator::operator=(const std::string& dir) +{ + reset(dir); + return *this; +} + +DirectoryIterator& DirectoryIterator::operator++() +{ + next(); + return *this; +} + +static const struct mountOption { + const char* name; + int clear; + int flag; +} mountOptions[] = { + { "defaults", 0, 0 }, + { "ro", 0, MS_RDONLY }, + { "rw", 1, MS_RDONLY }, + { "suid", 1, MS_NOSUID }, + { "nosuid", 0, MS_NOSUID }, + { "dev", 1, MS_NODEV }, + { "nodev", 0, MS_NODEV }, + { "exec", 1, MS_NOEXEC }, + { "noexec", 0, MS_NOEXEC }, + { "sync", 0, MS_SYNCHRONOUS }, + { "async", 1, MS_SYNCHRONOUS }, + { "dirsync", 0, MS_DIRSYNC }, + { "remount", 0, MS_REMOUNT }, + { "mand", 0, MS_MANDLOCK }, + { "nomand", 1, MS_MANDLOCK }, + { "atime", 1, MS_NOATIME }, + { "noatime", 0, MS_NOATIME }, + { "diratime", 1, MS_NODIRATIME }, + { "nodiratime", 0, MS_NODIRATIME }, + { "bind", 0, MS_BIND }, + { "rbind", 0, MS_BIND | MS_REC }, + { "relatime", 0, MS_RELATIME }, + { "norelatime", 1, MS_RELATIME }, + { "strictatime", 0, MS_STRICTATIME }, + { "nostrictatime", 1, MS_STRICTATIME }, + { NULL, 0, 0 }, +}; + +static unsigned long parseMountOptions(const std::string& opts, std::string& mntdata) +{ + std::stringstream optsSstream(opts); + const struct mountOption* mo; + unsigned long mntflags = 0L; + std::string opt; + + while (std::getline(optsSstream, opt, ',')) { + for (mo = mountOptions; mo->name != NULL; mo++) { + if (opt == mo->name) { + if (mo->clear) { + mntflags &= ~mo->flag; + } else { + mntflags |= mo->flag; + } + break; + } + if (mo->name != NULL) { + continue; + } + if (!mntdata.empty()) { + mntdata += ","; + } + mntdata += opt; + } + } + + return mntflags; +} + +void Mount::mountEntry(const std::string& src, const std::string& dest, const std::string& type, const std::string& opts) +{ + int ret; + unsigned long mntflags; + std::string mntdata; + + mntflags = parseMountOptions(opts, mntdata); + + ret = ::mount(src.c_str(), + dest.c_str(), + type.c_str(), + mntflags & ~MS_REMOUNT, + mntdata.c_str()); + + if (ret) { + if ((mntflags & MS_REMOUNT) || (mntflags & MS_BIND)) { + ret = ::mount(src.c_str(), + dest.c_str(), + type.c_str(), + mntflags | MS_REMOUNT, + mntdata.c_str()); + } + + if (ret) { + throw runtime::Exception("failed to mount " + src + " on " + dest); + } + } +} + +} // namespace runtime diff --git a/common/filesystem.h b/common/filesystem.h new file mode 100644 index 0000000..20b8a6e --- /dev/null +++ b/common/filesystem.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_FILESYSTEM_H__ +#define __RUNTIME_FILESYSTEM_H__ + +#include + +#include +#include + +namespace runtime { + +class File { +public: + File(); + File(const char* pathname); + File(const std::string& pathname); + File(const File& file); + File(const std::string& path, int flags); + + ~File(); + + File& operator=(const std::string& pathname) + { + path = pathname; + return *this; + } + + File& operator=(const File& file) + { + path = file.path; + return *this; + } + + bool operator<(const File& file) const; + bool operator>(const File& file) const; + bool operator<=(const File& file) const; + bool operator>=(const File& file) const; + + bool operator==(const File& file) const + { + return (path == file.path); + } + + bool operator!=(const File& file) const + { + return !(path == file.path); + } + + bool exists() const; + bool canRead() const; + bool canWrite() const; + bool canExecute() const; + + bool isLink() const; + bool isFile() const; + bool isDirectory() const; + bool isDevice() const; + + mode_t getMode() const; + uid_t getUid() const; + gid_t getGid() const; + + size_t size() const; + + void create(mode_t mode); + void open(int flags); + void read(void *buffer, const size_t size) const; + void write(const void *buffer, const size_t size) const; + void close(); + File copyTo(const std::string& pathname); + void remove(bool recursive = false); + void makeBaseDirectory(uid_t uid = 0, gid_t gid = 0); + void makeDirectory(bool recursive = false, uid_t uid = 0, gid_t gid = 0); + + void lock() const; + void unlock() const; + + void chown(uid_t uid, gid_t gid, bool recursive = false); + void chmod(mode_t mode, bool recursive = false); + + const std::string& getPath() const + { + return path; + } + + const std::string getName() const + { + return path.substr(path.rfind('/') + 1); + } + +private: + int descriptor; + std::string path; +}; + +class DirectoryIterator { +public: + DirectoryIterator(); + DirectoryIterator(const std::string& dir); + + ~DirectoryIterator(); + + DirectoryIterator& operator=(const std::string& dir); + DirectoryIterator& operator++(); + + bool operator==(const DirectoryIterator& iterator) const + { + return (current == iterator.current); + } + + bool operator!=(const DirectoryIterator& iterator) const + { + return !(current == iterator.current); + } + + const File& operator*() const + { + return current; + } + + File& operator*() + { + return current; + } + + const File* operator->() const + { + return ¤t; + } + + File* operator->() + { + return ¤t; + } + +private: + void next(); + void reset(const std::string& dir); + + File current; + DIR* directoryHandle; + std::string basename; +}; + +class Mount final { +public: + Mount() = delete; + + static void mountEntry(const std::string& src, const std::string& dest, + const std::string& type, const std::string& opts); +}; + +int Open(const std::string& path, int flags, mode_t mode); +void Close(int fd); + +} // namespace runtime +#endif //__RUNTIME_FILESYSTEM_H__ diff --git a/common/mainloop.cpp b/common/mainloop.cpp new file mode 100644 index 0000000..dcb1d0e --- /dev/null +++ b/common/mainloop.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include + +#include +#include + +#include + +#include "error.h" +#include "exception.h" +#include "mainloop.h" + +#define MAX_EPOLL_EVENTS 16 + +namespace runtime { + +namespace { + +gboolean GIOCallback(GIOChannel* channel, GIOCondition condition, void *data) +{ + Mainloop* mainloop = reinterpret_cast(data); + mainloop->dispatch(-1); + return TRUE; +} + +} // namespace + +Mainloop::Mainloop() : + pollFd(::epoll_create1(EPOLL_CLOEXEC)), + stopped(false) +{ + if (pollFd == -1) { + throw Exception(GetSystemErrorMessage()); + } +} + +Mainloop::~Mainloop() +{ + if (!callbacks.empty()) { + //assert(0 && "callback list is not empty"); + } + + ::close(pollFd); +} + +void Mainloop::addEventSource(const int fd, const Event events, Callback&& callback) +{ + epoll_event event; + std::lock_guard lock(mutex); + + if (callbacks.find(fd) != callbacks.end()) { + throw Exception("Event source already registered"); + } + + ::memset(&event, 0, sizeof(epoll_event)); + + event.events = events; + event.data.fd = fd; + + if (::epoll_ctl(pollFd, EPOLL_CTL_ADD, fd, &event) == -1) { + throw Exception(GetSystemErrorMessage()); + } + + callbacks.insert({fd, std::make_shared(std::move(callback))}); +} + +void Mainloop::removeEventSource(const int fd) +{ + std::lock_guard lock(mutex); + + auto iter = callbacks.find(fd); + if (iter == callbacks.end()) { + return; + } + + callbacks.erase(iter); + + ::epoll_ctl(pollFd, EPOLL_CTL_DEL, fd, NULL); +} + +bool Mainloop::dispatch(const int timeout) +{ + int nfds; + epoll_event event[MAX_EPOLL_EVENTS]; + + do { + nfds = ::epoll_wait(pollFd, event, MAX_EPOLL_EVENTS, timeout); + } while ((nfds == -1) && (errno == EINTR)); + + if (nfds < 0) { + throw Exception(GetSystemErrorMessage()); + } + + for (int i = 0; i < nfds; i++) { + std::lock_guard lock(mutex); + + auto iter = callbacks.find(event[i].data.fd); + if (iter == callbacks.end()) { + continue; + } + + std::shared_ptr callback(iter->second); + try { + if ((event[i].events & (EPOLLHUP | EPOLLRDHUP))) { + event[i].events &= ~EPOLLIN; + } + + (*callback)(event[i].data.fd, event[i].events); + } catch (std::exception& e) { + std::cout << "EXCEPTION ON MAINLOOP" << std::endl; + } + } + + return true; +} + +void Mainloop::stop() +{ + wakeupSignal.send(); +} + +void Mainloop::prepare() +{ + auto wakeupMainloop = [this](int fd, Mainloop::Event event) { + wakeupSignal.receive(); + removeEventSource(wakeupSignal.getFd()); + stopped = true; + }; + + addEventSource(wakeupSignal.getFd(), EPOLLIN, wakeupMainloop); +} + +void Mainloop::run(bool useGMainloop) +{ + prepare(); + + if (useGMainloop) { + GIOChannel* channel; + channel = g_io_channel_unix_new(pollFd); + if (channel == NULL) { + std::cout << "GMAINLOOP CHANNEL ALLOC FAILED" << std::endl; + return; + } + g_io_add_watch(channel, (GIOCondition)(G_IO_IN|G_IO_HUP), GIOCallback, this); + g_io_channel_unref(channel); + + while (!stopped) { + g_main_iteration(TRUE); + } + } else { + while (!stopped) { + dispatch(-1); + } + } +} + +} // namespace runtime diff --git a/common/mainloop.h b/common/mainloop.h new file mode 100644 index 0000000..4b55729 --- /dev/null +++ b/common/mainloop.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_MAINLOOP_H__ +#define __RUNTIME_MAINLOOP_H__ + +#include + +#include +#include +#include +#include +#include +#include + +#include "eventfd.h" + +namespace runtime { + +class Mainloop { +public: + typedef unsigned int Event; + typedef std::function Callback; + + Mainloop(); + ~Mainloop(); + + void addEventSource(const int fd, const Event events, Callback&& callback); + void removeEventSource(const int fd); + bool dispatch(const int timeout); + void run(bool useGMainloop = false); + void stop(); + +private: + typedef std::recursive_mutex Mutex; + + std::unordered_map> callbacks; + Mutex mutex; + int pollFd; + std::atomic stopped; + runtime::EventFD wakeupSignal; + + void prepare(); +}; + +} // namespace runtime + +#endif //__RUNTIME_MAINLOOP_H__ diff --git a/common/pam.cpp b/common/pam.cpp new file mode 100644 index 0000000..4759cd5 --- /dev/null +++ b/common/pam.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include + +#include +#include + +#include "pam.h" + +#include "exception.h" + +namespace runtime { + +PAM::PAM(const std::string& service, const std::string& user) +{ + struct pam_conv pamc; + + int error = ::pam_start(service.c_str(), user.c_str(), &pamc, &pamh); + if (error != PAM_SUCCESS) { + throw runtime::Exception("PAM Error"); + } +} + +PAM::~PAM() +{ + int error = ::pam_end(pamh, PAM_SUCCESS); + if (error != PAM_SUCCESS) { + throw runtime::Exception("PAM Error"); + } +} + +void PAM::setData(const std::string &name, void* data, void (*cleanup)(pam_handle_t* pamh, void* data, int error)) +{ + int error = ::pam_set_data(pamh, name.c_str(), data, cleanup); + if (error != PAM_SUCCESS) { + throw runtime::Exception("PAM Error"); + } +} + +const void* PAM::getData(const std::string &name) const +{ + const void* ret; + int error = ::pam_get_data(pamh, name.c_str(), &ret); + if (error != PAM_SUCCESS) { + throw runtime::Exception("PAM Error"); + } + return ret; +} + +void PAM::setItem(int item, void* data) +{ + int error = ::pam_set_item(pamh, item, data); + if (error != PAM_SUCCESS) { + throw runtime::Exception("PAM Error"); + } +} + +const void* PAM::getItem(int item) const +{ + const void* ret; + int error = ::pam_get_item(pamh, item, &ret); + if (error != PAM_SUCCESS) { + throw runtime::Exception("PAM Error"); + } + return ret; +} + +const std::string PAM::getUser(const std::string &prompt) const +{ + const char* user; + int error = ::pam_get_user(pamh, &user, prompt.c_str()); + if (error != PAM_SUCCESS) { + throw runtime::Exception("PAM Error"); + } + return std::string(user); +} + +void PAM::putEnv(const std::string &name_value) +{ + int error = ::pam_putenv(pamh, name_value.c_str()); + if (error != PAM_SUCCESS) { + throw runtime::Exception("PAM Error"); + } +} + +const std::string PAM::getEnv(const std::string &name) const +{ + const char* value = ::pam_getenv(pamh, name.c_str()); + if (value == NULL) { + throw runtime::Exception("PAM Error"); + } + return value; +} + +const std::vector PAM::getEnvList() const +{ + std::vector ret; + char** array = ::pam_getenvlist(pamh); + if (array == NULL) { + throw runtime::Exception("PAM Error"); + } + for (int i = 0; array[i] != NULL; i++) { + ret.push_back(array[i]); + } + return ret; +} + +void PAM::syslog(const std::string &log, int priority) +{ + ::pam_syslog(pamh, priority, "%s", log.c_str()); +} + + +int PAM::authenticate(int flags) +{ + return ::pam_authenticate(pamh, flags); +} + +int PAM::setCredential(int flags) +{ + return ::pam_setcred(pamh, flags); +} + +int PAM::accountManagement(int flags) +{ + return ::pam_acct_mgmt(pamh, flags); +} + +int PAM::changeAuthenticationToken(int flags) +{ + return ::pam_chauthtok(pamh, flags); +} + +void PAM::openSession(int flags) +{ + int error = ::pam_open_session(pamh, flags); + if (error != PAM_SUCCESS) { + throw runtime::Exception("PAM Error"); + } +} + +void PAM::closeSession(int flags) +{ + int error = ::pam_close_session(pamh, flags); + if (error != PAM_SUCCESS) { + throw runtime::Exception("PAM Error"); + } +} + +} // namespace runtime diff --git a/common/pam.h b/common/pam.h new file mode 100644 index 0000000..93e1b05 --- /dev/null +++ b/common/pam.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_PAM_H__ +#define __RUNTIME_PAM_H__ + +#include +#include +#include + +#include +#include + +namespace runtime { + +class PAM final { +public: + PAM(PAM&&) = delete; + PAM(const PAM&) = delete; + PAM(const std::string& service, const std::string& user); + ~PAM(); + + PAM& operator=(const PAM&) = delete; + PAM& operator=(PAM &&) = delete; + + void setData(const std::string &name, void* data, void (*cleanup)(pam_handle_t* pamh, void* data, int error)); + const void* getData(const std::string &name) const; + + void setItem(int item, void* data); + const void* getItem(int item) const; + + const std::string getUser(const std::string &prompt = "") const; + + void putEnv(const std::string &name_value); + const std::string getEnv(const std::string &name) const; + const std::vector getEnvList() const; + + void syslog(const std::string &log, int priority = LOG_ERR); + + int authenticate(int flags); + int setCredential(int flags); + int accountManagement(int flags); + int changeAuthenticationToken(int flags); + void openSession(int flags); + void closeSession(int flags); + +private: + pam_handle_t* pamh; +}; + +} // namespace runtime +#endif // __RUNTIME_PAM_H__ diff --git a/common/preprocessor.h b/common/preprocessor.h new file mode 100644 index 0000000..ab653ba --- /dev/null +++ b/common/preprocessor.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_PREPROCESSOR_H__ +#define __RUNTIME_PREPROCESSOR_H__ + +#define STRINGIFY_(x) #x +#define STRINGIFY(x) STRINGIFY_(x) + +#define CONCATENATE(arg1, arg2) CONCATENATE1(arg1, arg2) +#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2) +#define CONCATENATE2(arg1, arg2) arg1##arg2 + +#define VAR_ARGS_SIZE(...) VAR_ARGS_SIZE_(__VA_ARGS__, FOR_EACH_VAR_ARGS_RSEQ_N()) +#define VAR_ARGS_SIZE_(...) FOR_EACH_VAR_ARGS_ARG_N(__VA_ARGS__) + +#define FOR_EACH_VAR_ARGS_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, N, ...) N +#define FOR_EACH_VAR_ARGS_RSEQ_N() 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 + +#define FOR_EACH_VAR_ARGS_1(what, x, ...) what(x) +#define FOR_EACH_VAR_ARGS_2(what, x, ...) what(x); FOR_EACH_VAR_ARGS_1(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_3(what, x, ...) what(x); FOR_EACH_VAR_ARGS_2(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_4(what, x, ...) what(x); FOR_EACH_VAR_ARGS_3(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_5(what, x, ...) what(x); FOR_EACH_VAR_ARGS_4(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_6(what, x, ...) what(x); FOR_EACH_VAR_ARGS_5(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_7(what, x, ...) what(x); FOR_EACH_VAR_ARGS_6(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_8(what, x, ...) what(x); FOR_EACH_VAR_ARGS_7(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_9(what, x, ...) what(x); FOR_EACH_VAR_ARGS_8(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_10(what, x, ...) what(x); FOR_EACH_VAR_ARGS_9(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_11(what, x, ...) what(x); FOR_EACH_VAR_ARGS_10(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_12(what, x, ...) what(x); FOR_EACH_VAR_ARGS_11(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_13(what, x, ...) what(x); FOR_EACH_VAR_ARGS_12(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_14(what, x, ...) what(x); FOR_EACH_VAR_ARGS_13(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_15(what, x, ...) what(x); FOR_EACH_VAR_ARGS_14(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_16(what, x, ...) what(x); FOR_EACH_VAR_ARGS_15(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_17(what, x, ...) what(x); FOR_EACH_VAR_ARGS_16(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_18(what, x, ...) what(x); FOR_EACH_VAR_ARGS_17(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_19(what, x, ...) what(x); FOR_EACH_VAR_ARGS_18(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_20(what, x, ...) what(x); FOR_EACH_VAR_ARGS_19(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_21(what, x, ...) what(x); FOR_EACH_VAR_ARGS_20(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_22(what, x, ...) what(x); FOR_EACH_VAR_ARGS_21(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_23(what, x, ...) what(x); FOR_EACH_VAR_ARGS_22(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_24(what, x, ...) what(x); FOR_EACH_VAR_ARGS_23(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_25(what, x, ...) what(x); FOR_EACH_VAR_ARGS_24(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_26(what, x, ...) what(x); FOR_EACH_VAR_ARGS_25(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_27(what, x, ...) what(x); FOR_EACH_VAR_ARGS_26(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_28(what, x, ...) what(x); FOR_EACH_VAR_ARGS_27(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_29(what, x, ...) what(x); FOR_EACH_VAR_ARGS_28(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_30(what, x, ...) what(x); FOR_EACH_VAR_ARGS_29(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_31(what, x, ...) what(x); FOR_EACH_VAR_ARGS_30(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS_32(what, x, ...) what(x); FOR_EACH_VAR_ARGS_31(what, __VA_ARGS__) + +#define FOR_EACH_VAR_ARGS_(N, what, ...) CONCATENATE(FOR_EACH_VAR_ARGS_, N)(what, __VA_ARGS__) +#define FOR_EACH_VAR_ARGS(what, ...) FOR_EACH_VAR_ARGS_(VAR_ARGS_SIZE(__VA_ARGS__), what, __VA_ARGS__) + +#define SEQUENCE_1(how) how(1) +#define SEQUENCE_2(how) SEQUENCE_1(how), how(2) +#define SEQUENCE_3(how) SEQUENCE_2(how), how(3) +#define SEQUENCE_4(how) SEQUENCE_3(how), how(4) +#define SEQUENCE_5(how) SEQUENCE_4(how), how(5) +#define SEQUENCE_6(how) SEQUENCE_5(how), how(6) +#define SEQUENCE_7(how) SEQUENCE_6(how), how(7) +#define SEQUENCE_8(how) SEQUENCE_7(how), how(8) +#define SEQUENCE_9(how) SEQUENCE_8(how), how(9) +#define SEQUENCE_10(how) SEQUENCE_9(how), how(10) +#define SEQUENCE_11(how) SEQUENCE_10(how), how(11) +#define SEQUENCE_12(how) SEQUENCE_11(how), how(12) +#define SEQUENCE_13(how) SEQUENCE_12(how), how(13) +#define SEQUENCE_14(how) SEQUENCE_13(how), how(14) +#define SEQUENCE_15(how) SEQUENCE_14(how), how(15) +#define SEQUENCE_16(how) SEQUENCE_15(how), how(16) +#define SEQUENCE_17(how) SEQUENCE_16(how), how(17) +#define SEQUENCE_18(how) SEQUENCE_17(how), how(18) +#define SEQUENCE_19(how) SEQUENCE_18(how), how(19) +#define SEQUENCE_20(how) SEQUENCE_19(how), how(20) +#define SEQUENCE_21(how) SEQUENCE_20(how), how(21) +#define SEQUENCE_22(how) SEQUENCE_21(how), how(22) +#define SEQUENCE_23(how) SEQUENCE_22(how), how(23) +#define SEQUENCE_24(how) SEQUENCE_23(how), how(24) +#define SEQUENCE_25(how) SEQUENCE_24(how), how(25) +#define SEQUENCE_26(how) SEQUENCE_25(how), how(26) +#define SEQUENCE_27(how) SEQUENCE_26(how), how(27) +#define SEQUENCE_28(how) SEQUENCE_27(how), how(28) +#define SEQUENCE_29(how) SEQUENCE_28(how), how(29) +#define SEQUENCE_30(how) SEQUENCE_29(how), how(30) +#define SEQUENCE_31(how) SEQUENCE_30(how), how(31) +#define SEQUENCE_32(how) SEQUENCE_31(how), how(32) +#define SEQUENCE(how, N) SEQUENCE_##N(how) + +#endif //!__RUNTIME_PREPROCESSOR_H__ diff --git a/common/process.cpp b/common/process.cpp new file mode 100644 index 0000000..7428dab --- /dev/null +++ b/common/process.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include + +#include "process.h" +#include "error.h" +#include "exception.h" + +namespace runtime { + +Process::Process(const std::string& prog) : + status(-1), pid(-1), program(prog) +{ + args.push_back(prog); +} + +Process::Process(const std::string& prog, const std::vector& args) : + status(-1), pid(-1), program(prog), args(args) +{ +} + +Process::~Process() +{ +} + +int Process::execute() +{ + pid = ::fork(); + if (pid == -1) { + return -1; + } + + if (pid == 0) { + const char** argv = new const char *[args.size() + 1]; + + int i = 0; + for (std::string & arg : args) { + argv[i++] = arg.c_str(); + } + argv[i] = NULL; + + ::execv(program.c_str(), const_cast(argv)); + std::quick_exit(EXIT_FAILURE); + } + + return pid; +} + +int Process::waitForFinished() +{ + while (::waitpid(pid, &status, 0) == -1) { + if (errno != EINTR) { + return -1; + } + } + + return status; +} + +bool Process::isRunning() const +{ + if (::kill(pid, 0) == 0) { + return true; + } + + return false; +} + +void Process::kill() +{ + if (::kill(pid, SIGKILL) == -1) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } +} + +void Process::terminate() +{ + if (::kill(pid, SIGINT) == -1) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } +} + +} // namespace runtime diff --git a/common/process.h b/common/process.h new file mode 100644 index 0000000..9b629a2 --- /dev/null +++ b/common/process.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_PROCESS_H__ +#define __RUNTIME_PROCESS_H__ + +#include +#include + +namespace runtime { + +class Process { +public: + typedef pid_t Pid; + + Process(const std::string& prog); + Process(const std::string& prog, const std::vector& args); + Process(const Process& proc) = delete; + + ~Process(); + + Process& operator=(const Process& proc) = delete; + + int execute(); + int start(); + int waitForFinished(); + int waitForStarted(); + void terminate(); + void kill(); + + bool isRunning() const; + +private: + int status; + Pid pid; + std::string program; + std::vector args; +}; + +} // namespace runtime +#endif //__RUNTIME_PROCESS_H__ diff --git a/common/reflection.h b/common/reflection.h new file mode 100644 index 0000000..7f6bfde --- /dev/null +++ b/common/reflection.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_REFLECTION_H__ +#define __RUNTIME_REFLECTION_H__ + +#include + +#include "preprocessor.h" + +#define VISIT_ELEMENT(elem) v.visit(#elem, elem) + +#define REFLECTABLE(...) \ +template \ +void accept(V v) \ +{ \ + FOR_EACH_VAR_ARGS(VISIT_ELEMENT, __VA_ARGS__); \ +} \ +template \ +void accept(V v) const \ +{ \ + FOR_EACH_VAR_ARGS(VISIT_ELEMENT, __VA_ARGS__); \ +} + +#define NO_REFLECTABLE_PROPERTY \ + template \ + static void accept(V) {} + +template +struct ReflectionTraitChecker { + struct Visitor {}; + + template static std::true_type + test(decltype(std::declval().template accept(Visitor()))*); + + template static std::false_type + test(...); + + static constexpr bool value = std::is_same(0)), std::true_type>::value; +}; + +template +struct IsReflectable : public std::integral_constant::value> {}; + +#endif //!__RUNTIME_REFLECTION_H__ diff --git a/common/rmi/callback-holder.h b/common/rmi/callback-holder.h new file mode 100644 index 0000000..fc22950 --- /dev/null +++ b/common/rmi/callback-holder.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RMI_CALLBACK_HOLDER_H__ +#define __RMI_CALLBACK_HOLDER_H__ + +#include +#include + +#include "message.h" + +namespace rmi { + +template +struct MethodHandler { + typedef std::function type; +}; +// using MethodHandler = std::function; + +template +struct CallbackHolder { + template + struct Sequence {}; + + template + struct SequenceExpansion : SequenceExpansion {}; + + template + struct SequenceExpansion<0, S...> { + typedef Sequence type; + }; + + std::tuple parameters; + const typename MethodHandler::type& callback; + + CallbackHolder(const typename MethodHandler::type& m) : + callback(m) + { + } + + Type dispatch(Message& message) + { + return callCallback(message, typename SequenceExpansion::type()); + } + + template + Type callCallback(Message& message, R&... args) + { + message.unpackParameters(args...); + return callback(args...); + } + + template + Type callCallback(Message& message, Sequence) + { + return callCallback(message, std::get(parameters)...); + } +}; + +} // namespace rmi +#endif //!__RMI_CALLBACK_HOLDER_H__ diff --git a/common/rmi/client.cpp b/common/rmi/client.cpp new file mode 100644 index 0000000..a913446 --- /dev/null +++ b/common/rmi/client.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "client.h" + +namespace rmi { + +Client::Client(const std::string& path) : + address(path) +{ +} + +Client::~Client() +{ + disconnect(); +} + +void Client::connect() +{ + connection = std::make_shared(Socket::connect(address)); + + dispatcher = std::thread([this] { mainloop.run(); }); +} + +int Client::unsubscribe(const std::string& provider, int id) +{ + // file descriptor(id) is automatically closed when mainloop callback is destroyed. + mainloop.removeEventSource(id); + return 0; +} + +int Client::subscribe(const std::string& provider, const std::string& name) +{ + Message request = connection->createMessage(Message::MethodCall, provider); + request.packParameters(name); + connection->send(request); + + FileDescriptor response; + Message reply = connection->dispatch(); + reply.disclose(response); + + return response.fileDescriptor; +} + +void Client::disconnect() +{ + mainloop.stop(); + if (dispatcher.joinable()) { + dispatcher.join(); + } +} + +} // namespace rmi diff --git a/common/rmi/client.h b/common/rmi/client.h new file mode 100644 index 0000000..53fe5b1 --- /dev/null +++ b/common/rmi/client.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RMI_CLIENT_H__ +#define __RMI_CLIENT_H__ + +#include +#include +#include + +#include "error.h" +#include "message.h" +#include "connection.h" +#include "mainloop.h" +#include "callback-holder.h" + +namespace rmi { + +class Client { +public: + Client(const std::string& address); + ~Client(); + + Client(const Client&) = delete; + Client& operator=(const Client&) = delete; + + void connect(); + void disconnect(); + + int subscribe(const std::string& provider, const std::string& name); + + template + int subscribe(const std::string& provider, const std::string& name, + const typename MethodHandler::type& handler); + + int unsubscribe(const std::string& provider, int handle); + + template + Type methodCall(const std::string& method, Args&&... args); + +private: + std::string address; + std::shared_ptr connection; + runtime::Mainloop mainloop; + std::thread dispatcher; +}; + +template +int Client::subscribe(const std::string& provider, const std::string& name, + const typename MethodHandler::type& handler) +{ + int id = subscribe(provider, name); + if (id < 0) { + return -1; + } + + std::shared_ptr transport = std::make_shared(id); + + auto callback = [handler, transport, this](int fd, runtime::Mainloop::Event event) { + if ((event & EPOLLHUP) || (event & EPOLLRDHUP)) { + mainloop.removeEventSource(fd); + return; + } + + try { + Message msg; + msg.decode(*transport); + + CallbackHolder callback(handler); + callback.dispatch(msg); + } catch (std::exception& e) { + std::cout << e.what() << std::endl; + } + }; + + mainloop.addEventSource(id, EPOLLIN | EPOLLHUP | EPOLLRDHUP, callback); + + return id; +} + +template +Type Client::methodCall(const std::string& method, Args&&... args) +{ + Message request = connection->createMessage(Message::MethodCall, method); + request.packParameters(std::forward(args)...); + connection->send(request); + + Type response; + Message reply = connection->dispatch(); + reply.disclose(response); + + return response; +} + +} // namespace rmi +#endif //__RMI_CLIENT_H__ diff --git a/common/rmi/connection.cpp b/common/rmi/connection.cpp new file mode 100644 index 0000000..9153a81 --- /dev/null +++ b/common/rmi/connection.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +#include "connection.h" + +namespace rmi { + +Connection::Connection(Socket&& sock) : + socket(std::move(sock)) +{ +} + +Connection::~Connection() noexcept +{ +} + +Message Connection::createMessage(unsigned int type, const std::string& target) +{ + return Message(type, target); +} + +void Connection::send(const Message& message) const +{ + std::lock_guard lock(transmitMutex); + message.encode(socket); +} + +Message Connection::dispatch() const +{ + Message message; + std::lock_guard lock(receiveMutex); + + message.decode(socket); + if (message.isError()) { + std::string exception; + message.disclose(exception); + + throw runtime::Exception(exception); + } + + return message; +} + +} // namespace rmi diff --git a/common/rmi/connection.h b/common/rmi/connection.h new file mode 100644 index 0000000..0b943e2 --- /dev/null +++ b/common/rmi/connection.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RMI_CONNECTION_H__ +#define __RMI_CONNECTION_H__ + +#include +#include + +#include "socket.h" +#include "serialize.h" +#include "message.h" + +namespace rmi { + +class Connection { +public: + Connection(Socket&& sock); + Connection(const Connection&) = delete; + ~Connection() noexcept; + + Connection& operator=(const Connection&) = delete; + Connection& operator=(Connection&) = delete; + + Message createMessage(unsigned int type, const std::string& target); + + void send(const Message& message) const; + Message dispatch() const; + + int getFd() const + { + return socket.getFd(); + } + + Credentials getPeerCredentials() const + { + return socket.getPeerCredentials(); + } + +private: + Socket socket; + mutable std::mutex receiveMutex; + mutable std::mutex transmitMutex; +}; + +} // namespace rmi +#endif //__RMI_CONNECTION_H__ diff --git a/common/rmi/message-composer.cpp b/common/rmi/message-composer.cpp new file mode 100644 index 0000000..cdb29aa --- /dev/null +++ b/common/rmi/message-composer.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "message-composer.h" + +namespace rmi { + +MessageComposer::MessageComposer(size_t caps) : + capacity(caps), + produce(0), + consume(0), + buffer(new char[caps]) +{ +} + +MessageComposer::MessageComposer(const MessageComposer& rhs) : + capacity(rhs.capacity), + produce(rhs.produce), + consume(rhs.consume), + buffer(new char[rhs.capacity]) +{ + std::copy(rhs.buffer + consume, rhs.buffer + produce, buffer + consume); +} + +MessageComposer::MessageComposer(MessageComposer&& rhs) : + capacity(0), + produce(0), + consume(0), + buffer(nullptr) +{ + buffer = rhs.buffer; + capacity = rhs.capacity; + produce = rhs.produce; + consume = rhs.consume; + + // Release buffer pointer from the source object so that + // the destructor does not free the memory multiple times. + + rhs.buffer = nullptr; + rhs.produce = 0; + rhs.consume = 0; +} + +MessageComposer::~MessageComposer() +{ + if (buffer != nullptr) { + delete[] buffer; + } +} + +MessageComposer& MessageComposer::operator=(const MessageComposer& rhs) +{ + if (this != &rhs) { + delete[] buffer; + + capacity = rhs.capacity; + produce = rhs.produce; + consume = rhs.consume; + buffer = new char[capacity]; + std::copy(rhs.buffer + consume, rhs.buffer + produce, buffer + consume); + } + + return *this; +} + +MessageComposer& MessageComposer::operator=(MessageComposer&& rhs) +{ + if (this != &rhs) { + // Free existing buffer + delete[] buffer; + + // Copy the buffer pointer and its attributes from the + // source object. + buffer = rhs.buffer; + produce = rhs.produce; + consume = rhs.consume; + capacity = rhs.capacity; + + // Release buffer pointer from the source object so that + // the destructor does not free the memory multiple times. + rhs.buffer = nullptr; + rhs.produce = 0; + rhs.consume = 0; + rhs.capacity = 0; + } + + return *this; +} + +void MessageComposer::write(const void* ptr, const size_t sz) +{ + size_t bytes = sz; + if ((produce + bytes) > capacity) { + bytes = capacity - produce; + } + + ::memcpy(reinterpret_cast(buffer + produce), ptr, bytes); + produce += bytes; +} + +void MessageComposer::read(void* ptr, const size_t sz) +{ + size_t bytes = sz; + if ((consume + bytes) > produce) { + bytes = produce - consume; + } + + ::memcpy(ptr, reinterpret_cast(buffer) + consume, bytes); + consume += bytes; + + // Reset cursors if there is no data + if (consume == produce) { + consume = produce = 0; + } +} + +} // namespae rmi diff --git a/common/rmi/message-composer.h b/common/rmi/message-composer.h new file mode 100644 index 0000000..377b817 --- /dev/null +++ b/common/rmi/message-composer.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RMI_MESSAGE_COMPOSER_H__ +#define __RMI_MESSAGE_COMPOSER_H__ + +#include +#include +#include +#include + +namespace rmi { + +class MessageComposer { +public: + MessageComposer(size_t caps = 4096); + MessageComposer(const MessageComposer& rhs); + MessageComposer(MessageComposer&& rhs); + + ~MessageComposer(); + + MessageComposer& operator=(const MessageComposer& rhs); + MessageComposer& operator=(MessageComposer&& rhs); + + void write(const void* ptr, const size_t sz); + void read(void* ptr, const size_t sz); + + void reserve(size_t size) + { + produce = size; + } + + void reset() + { + produce = consume = 0; + } + + char* begin() const + { + return buffer + consume; + } + + char* end() const + { + return buffer + produce; + } + + size_t size() const + { + return (end() - begin()); + } + +private: + size_t capacity; + size_t produce; + size_t consume; + char *buffer; +}; + +} // namespae rmi +#endif //__RMI_MESSAGE_COMPOSER_H__ diff --git a/common/rmi/message.cpp b/common/rmi/message.cpp new file mode 100644 index 0000000..256da2c --- /dev/null +++ b/common/rmi/message.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "message.h" +#include "exception.h" + +namespace rmi { + +std::atomic Message::sequence(0); + +Message::Message() : + signature({sequence++, Invalid, ""}) +{ +} + +Message::Message(unsigned int id, unsigned int type, const std::string& target) : + signature({id, type, target}) +{ + enclose(signature); +} + +Message::Message(unsigned int type, const std::string& target) : + signature({sequence++, type, target}) +{ + enclose(signature); +} + +Message::Message(Message&& rhs) + : signature(std::move(rhs.signature)), + buffer(std::move(rhs.buffer)), + fileDescriptors(std::move(rhs.fileDescriptors)) +{ +} + +Message::~Message() +{ +} + +Message::Message(const Message& rhs) : + signature(rhs.signature), + buffer(rhs.buffer) +{ + enclose(signature); +} + +Message& Message::operator=(const Message& rhs) +{ + if (this != &rhs) { + buffer = rhs.buffer; + signature = rhs.signature; + } + + return *this; +} + +Message& Message::operator=(Message&& rhs) +{ + if (this != &rhs) { + buffer = std::move(rhs.buffer); + signature = std::move(rhs.signature); + fileDescriptors = std::move(rhs.fileDescriptors); + } + + return *this; +} + +Message Message::createReplyMessage() const +{ + return Message(id(), Reply, target()); +} + +Message Message::createErrorMessage(const std::string& message) const +{ + Message error(id(), Error, target()); + error.enclose(message); + + return error; +} + +template<> void Message::enclose(FileDescriptor&& fd) +{ + if (fd.fileDescriptor == -1) { + throw runtime::Exception("Invalid file descriptor"); + } + + fileDescriptors.push_back(std::move(fd)); +} + +template<> void Message::disclose(FileDescriptor& fd) +{ + if (!fileDescriptors.empty()) { + fd.fileDescriptor = std::move(fileDescriptors.front()).fileDescriptor; + fileDescriptors.pop_front(); + } +} + +} // namespace rmi diff --git a/common/rmi/message.h b/common/rmi/message.h new file mode 100644 index 0000000..a54f360 --- /dev/null +++ b/common/rmi/message.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RMI_MESSAGE_H__ +#define __RMI_MESSAGE_H__ + +#include +#include +#include +#include +#include +#include + +#include "message-composer.h" + +#include "reflection.h" +#include "serialize.h" +#include "file-descriptor.h" + +namespace rmi { + +class Message { +public: + enum Type { + Invalid, + MethodCall, + Reply, + Error, + Signal + }; + + Message(); + Message(unsigned int id, unsigned int type, const std::string&); + Message(unsigned int type, const std::string&); + Message(const Message& rhs); + Message(Message&& rhs); + + ~Message(); + + Message& operator=(const Message& rhs); + Message& operator=(Message&& rhs); + + // [TBD] Take arguments + Message createReplyMessage() const; + Message createErrorMessage(const std::string& message) const; + + unsigned int id() const + { + return signature.id; + } + + unsigned int type() const + { + return signature.type; + } + + const std::string& target() const + { + return signature.target; + } + + bool isInvalid() const + { + return type() == Invalid; + } + + bool isError() const + { + return type() == Error; + } + + bool isMethodCall() const + { + return type() == MethodCall; + } + + bool isSignal() const + { + return type() == Signal; + } + + bool isReply() const + { + return type() == Reply; + } + + template + void encode(const T& device) const; + + template + void decode(const T& device); + + void packParameters() + { + } + + template + void packParameters(F&& arg); + + template + void packParameters(F&& first, R&&... rest); + + void unpackParameters() + { + } + + template + void unpackParameters(F& arg); + + template + void unpackParameters(F& first, R&... rest); + + template + void enclose(DataType&& data); + + template + void disclose(DataType& data); + +private: + struct MessageHeader { + unsigned int id; // Unique message id + unsigned int type; // Mesage type + size_t length;// Total message length except MessageHeader itself + size_t ancillary; + }; + + struct MessageSignature { + unsigned int id; + unsigned int type; + std::string target; + + REFLECTABLE( + id, + type, + target + ) + }; + + MessageSignature signature; + MessageComposer buffer; + std::deque fileDescriptors; + + static std::atomic sequence; +}; + +template +void Message::packParameters(F&& arg) +{ + enclose(std::forward(arg)); +} + +template +void Message::packParameters(F&& first, R&&... rest) +{ + packParameters(std::forward(first)); + packParameters(std::forward(rest)...); +} + +template +void Message::unpackParameters(F& arg) +{ + disclose(arg); +} + +template +void Message::unpackParameters(F& first, R&... rest) +{ + unpackParameters(first); + unpackParameters(rest...); +} + +template +void Message::enclose(DataType&& data) +{ + runtime::Serializer serializer(buffer); + runtime::SerializableArgument arg(std::forward(data)); + arg.accept(serializer); +} + +template +void Message::disclose(DataType& data) +{ + runtime::Deserializer deserializer(buffer); + runtime::DeserializableArgument arg(data); + arg.accept(deserializer); +} + +template +void Message::encode(const T& device) const +{ + MessageHeader header = { + signature.id, + signature.type, + buffer.size(), + fileDescriptors.size() + }; + + device.write(&header, sizeof(header)); + device.write(buffer.begin(), header.length); + + int i = 0, fds[fileDescriptors.size()]; + for (const FileDescriptor& fd : fileDescriptors) { + fds[i++] = fd.fileDescriptor; + } + + device.sendFileDescriptors(fds, fileDescriptors.size()); +} + +template +void Message::decode(const T& device) +{ + MessageHeader header; + device.read(&header, sizeof(header)); + device.read(buffer.begin(), header.length); + buffer.reserve(header.length); + + int fds[header.ancillary]; + + device.receiveFileDescriptors(fds, header.ancillary); + for (unsigned int i = 0; i < header.ancillary; i++) { + fileDescriptors.emplace_back(FileDescriptor(fds[i])); + } + + disclose(signature); +} + +template<> void Message::enclose(FileDescriptor&& fd); +template<> void Message::disclose(FileDescriptor& fd); + +} // namespae rmi +#endif //__RMI_MESSAGE_H__ diff --git a/common/rmi/notification.cpp b/common/rmi/notification.cpp new file mode 100644 index 0000000..1e1dfd9 --- /dev/null +++ b/common/rmi/notification.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include + +#include "notification.h" +#include "exception.h" +#include "error.h" + +namespace rmi { + +Notification::Notification() +{ +} + +Notification::Notification(const std::string& name) : + signalName(name) +{ +} + +Notification::Notification(Notification&& rhs) : + signalName(std::move(rhs.signalName)), + subscribers(std::move(rhs.subscribers)) +{ +} + +SubscriptionId Notification::createSubscriber() +{ + int fds[2] = {-1, -1}; + if (::socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1) { + throw runtime::Exception("Failed to create socket pair"); + } + + std::lock_guard lock(subscriberLock); + subscribers.push_back(std::make_shared(fds[0])); + + return SubscriptionId(fds[0], fds[1]); +} + +int Notification::removeSubscriber(const int id) +{ + std::lock_guard lock(subscriberLock); + + std::list>::iterator it = subscribers.begin(); + + while (it != subscribers.end()) { + if ((*it)->getFd() == id) { + subscribers.erase(it); + return 0; + } + ++it; + } + + return -1; +} + +} // namespace rmi diff --git a/common/rmi/notification.h b/common/rmi/notification.h new file mode 100644 index 0000000..22d802e --- /dev/null +++ b/common/rmi/notification.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RMI_NOTIFICATION_H__ +#define __RMI_NOTIFICATION_H__ + +#include +#include +#include +#include +#include +#include +#include + +#include "socket.h" +#include "message.h" +#include "audit/logger.h" + +namespace rmi { + +typedef std::pair SubscriptionId; + +class Notification { +public: + Notification(); + Notification(const std::string& name); + Notification(const Notification&) = default; + Notification(Notification&&); + + SubscriptionId createSubscriber(); + int removeSubscriber(const int id); + + template + void notify(Args&&... args); + +private: + std::string signalName; + std::list> subscribers; + std::mutex subscriberLock; +}; + +template +void Notification::notify(Args&&... args) +{ + Message msg(Message::Signal, signalName); + msg.packParameters(std::forward(args)...); + + std::lock_guard lock(subscriberLock); + + for (const std::shared_ptr& subscriber : subscribers) { + try { + msg.encode(*subscriber); + } catch (runtime::Exception& e) { + ERROR(e.what()); + } + } +} + +} // namespae rmi +#endif //__RMI_NOTIFICATION_H__ diff --git a/common/rmi/service.cpp b/common/rmi/service.cpp new file mode 100644 index 0000000..0c3effb --- /dev/null +++ b/common/rmi/service.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include + +#include + +#include "exception.h" +#include "service.h" +#include "message.h" +#include "audit/logger.h" + +namespace rmi { + +thread_local Service::ProcessingContext Service::processingContext; + +Service::Service(const std::string& path) : + address(path), workqueue(5) +{ + setNewConnectionCallback(nullptr); + setCloseConnectionCallback(nullptr); +} + +Service::~Service() +{ +} + +void Service::start(bool useGMainloop) +{ + Socket socket(Socket::create(address)); + + auto accept = [&](int fd, runtime::Mainloop::Event event) { + onNewConnection(std::make_shared(socket.accept())); + }; + + mainloop.addEventSource(socket.getFd(), + EPOLLIN | EPOLLHUP | EPOLLRDHUP, + accept); + + mainloop.run(useGMainloop); +} + +void Service::stop() +{ +} + +Service::ConnectionRegistry::iterator Service::getConnectionIterator(const int id) +{ + return std::find_if(connectionRegistry.begin(), connectionRegistry.end(), + [id](const std::shared_ptr& connection) { + return id == connection->getFd(); + }); +} + +void Service::setPrivilegeChecker(const PrivilegeChecker& checker) +{ + auto check = [checker, this](const Credentials& cred, const std::string& privilege) { + return checker(cred, privilege); + }; + + onMethodCall = std::move(checker); +} + +void Service::setNewConnectionCallback(const ConnectionCallback& connectionCallback) +{ + auto callback = [connectionCallback, this](const std::shared_ptr& connection) { + auto handle = [&](int fd, runtime::Mainloop::Event event) { + std::lock_guard lock(stateLock); + + auto iter = getConnectionIterator(fd); + if (iter == connectionRegistry.end()) { + return; + } + + if ((event & EPOLLHUP) || (event & EPOLLRDHUP)) { + onCloseConnection(*iter); + connectionRegistry.erase(iter); + return; + } + + onMessageProcess(*iter); + }; + + if ((connectionCallback == nullptr) || + (connectionCallback(*connection) == true)) { + mainloop.addEventSource(connection->getFd(), + EPOLLIN | EPOLLHUP | EPOLLRDHUP, + handle); + std::lock_guard lock(stateLock); + connectionRegistry.push_back(connection); + } + }; + + std::lock_guard lock(stateLock); + onNewConnection = std::move(callback); +} + +void Service::setCloseConnectionCallback(const ConnectionCallback& closeCallback) +{ + auto callback = [closeCallback, this](const std::shared_ptr& connection) { + mainloop.removeEventSource(connection->getFd()); + if (closeCallback) { + closeCallback(*connection); + } + }; + + std::lock_guard lock(stateLock); + onCloseConnection = std::move(callback); +} + +void Service::createNotification(const std::string& name) +{ + std::lock_guard lock(notificationLock); + + if (notificationRegistry.count(name)) { + throw runtime::Exception("Notification already registered"); + } + + notificationRegistry.emplace(name, Notification(name)); +} + +int Service::subscribeNotification(const std::string& name) +{ + auto closeHandler = [&, name, this](int fd, runtime::Mainloop::Event event) { + if ((event & EPOLLHUP) || (event & EPOLLRDHUP)) { + unsubscribeNotification(name, fd); + return; + } + }; + + notificationLock.lock(); + if (!notificationRegistry.count(name)) { + notificationLock.unlock(); + return -1; + } + + Notification& notification = notificationRegistry[name]; + notificationLock.unlock(); + + try { + SubscriptionId slot = notification.createSubscriber(); + mainloop.addEventSource(slot.first, EPOLLHUP | EPOLLRDHUP, closeHandler); + return slot.second; + } catch (runtime::Exception& e) { + ERROR(e.what()); + return -1; + } + + return -1; +} + +int Service::unsubscribeNotification(const std::string& name, const int id) +{ + notificationLock.lock(); + + if (!notificationRegistry.count(name)) { + notificationLock.unlock(); + return -1; + } + + Notification& notification = notificationRegistry[name]; + notificationLock.unlock(); + + mainloop.removeEventSource(id); + + notification.removeSubscriber(id); + + return 0; +} + +void Service::onMessageProcess(const std::shared_ptr& connection) +{ + // The connection object can be destroyed in main-thread when peer is closed. + // To make sure that the connection object is valid on that situation, + // we should increase the reference count of the shared_ptr by capturing it as value + auto process = [&, connection](Message& request) { + try { + std::shared_ptr methodContext = methodRegistry.at(request.target()); + + processingContext = ProcessingContext(connection); + if (onMethodCall(processingContext.credentials, methodContext->privilege) != true) { + throw runtime::Exception("Permission denied"); + } + + connection->send(methodContext->dispatcher(request)); + } catch (std::exception& e) { + try { + // Forward the exception to the peer + connection->send(request.createErrorMessage(e.what())); + } catch (std::exception& ex) { + // The connection is abnormally closed by the peer. + ERROR(ex.what()); + } + } + }; + + try { + workqueue.submit(std::bind(process, connection->dispatch())); + } catch (std::exception& e) { + ERROR(e.what()); + } +} + +} // namespace rmi diff --git a/common/rmi/service.h b/common/rmi/service.h new file mode 100644 index 0000000..0dee955 --- /dev/null +++ b/common/rmi/service.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RMI_SERVICE_H__ +#define __RMI_SERVICE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "preprocessor.h" +#include "thread-pool.h" +#include "mainloop.h" +#include "connection.h" +#include "message.h" +#include "callback-holder.h" +#include "notification.h" + +#define STRIP_(...) +#define STRIP(x) STRIP_ x + +#define TYPEOF____(...) __VA_ARGS__ +#define TYPEOF___(...) (__VA_ARGS__), +#define TYPEOF__(x, ...) TYPEOF____ x +#define TYPEOF_(...) TYPEOF__(__VA_ARGS__) +#define TYPEOF(x) TYPEOF_(TYPEOF___ x, ) + +#define PLACEHOLDER(n) std::placeholders::_##n + +#define PROTOTYPE_(D, N) SEQUENCE(D, N) +#define PROTOTYPE(...) PROTOTYPE_(PLACEHOLDER, VAR_ARGS_SIZE(__VA_ARGS__)) + +#define registerMethod(T, P, M, ...) \ +setMethodHandler \ + (P, STRINGIFY(TYPEOF(STRIP(M))), std::bind(&TYPEOF(STRIP(M)), T, \ + PROTOTYPE(TYPEOF(STRIP(STRIP(M)))))) + +#define registerParametricMethod(T, P, M, ...) \ +setMethodHandler \ + (P, STRINGIFY(TYPEOF(STRIP(M))), std::bind(&TYPEOF(STRIP(M)), T, \ + PROTOTYPE(TYPEOF(STRIP(STRIP(M)))))) + +#define registerNonparametricMethod(T, P, M, ...) \ +setMethodHandler \ + (P, STRINGIFY(TYPEOF(STRIP(M))), std::bind(&TYPEOF(STRIP(M)), T)) + +namespace rmi { + +typedef std::function ConnectionCallback; +typedef std::function PrivilegeChecker; + +class Service { +public: + Service(const std::string& address); + ~Service(); + + Service(const Service&) = delete; + Service& operator=(const Service&) = delete; + + void start(bool useGMainloop = false); + void stop(); + + void setPrivilegeChecker(const PrivilegeChecker& checker); + void setNewConnectionCallback(const ConnectionCallback& callback); + void setCloseConnectionCallback(const ConnectionCallback& callback); + + template + void setMethodHandler(const std::string& privilege, const std::string& method, + const typename MethodHandler::type& handler); + + void createNotification(const std::string& name); + int subscribeNotification(const std::string& name); + int unsubscribeNotification(const std::string& name, const int id); + + template + void notify(const std::string& name, Args&&... args); + + pid_t getPeerPid() const + { + return processingContext.credentials.pid; + } + + uid_t getPeerUid() const + { + return processingContext.credentials.uid; + } + + gid_t getPeerGid() const + { + return processingContext.credentials.gid; + } + +private: + struct ProcessingContext { + ProcessingContext() = default; + ProcessingContext(const std::shared_ptr& connection) : + credentials(connection->getPeerCredentials()) + { + } + + Credentials credentials; + }; + + typedef std::list> ConnectionRegistry; + typedef std::function& connection)> CallbackDispatcher; + + typedef std::function MethodDispatcher; + + struct MethodContext { + MethodContext(const std::string& priv, MethodDispatcher&& disp) : + privilege(priv), dispatcher(std::move(disp)) + { + } + + std::string privilege; + MethodDispatcher dispatcher; + }; + + typedef std::unordered_map> MethodRegistry; + typedef std::unordered_map NotificationRegistry; + + void onMessageProcess(const std::shared_ptr& connection); + + ConnectionRegistry::iterator getConnectionIterator(const int id); + + CallbackDispatcher onNewConnection; + CallbackDispatcher onCloseConnection; + PrivilegeChecker onMethodCall; + + MethodRegistry methodRegistry; + NotificationRegistry notificationRegistry; + ConnectionRegistry connectionRegistry; + + runtime::Mainloop mainloop; + std::string address; + + runtime::ThreadPool workqueue; + std::mutex stateLock; + std::mutex notificationLock; + std::mutex methodRegistryLock; + + static thread_local ProcessingContext processingContext; +}; + +template +void Service::setMethodHandler(const std::string& privilege, const std::string& method, + const typename MethodHandler::type& handler) +{ + auto dispatchMethod = [handler](Message& message) { + CallbackHolder callback(handler); + Message reply = message.createReplyMessage(); + reply.packParameters(callback.dispatch(message)); + + return reply; + }; + + std::lock_guard lock(methodRegistryLock); + + if (methodRegistry.count(method)) { + throw runtime::Exception("Method handler already registered"); + } + + methodRegistry[method] = std::make_shared(privilege, dispatchMethod); +} + +template +void Service::notify(const std::string& name, Args&&... args) +{ + std::lock_guard lock(notificationLock); + + Notification& slot = notificationRegistry.at(name); + slot.notify(name, std::forward(args)...); +} + +} // namespace rmi + +#endif //__RMI_SERVICE_H__ diff --git a/common/rmi/socket.cpp b/common/rmi/socket.cpp new file mode 100644 index 0000000..3df11ce --- /dev/null +++ b/common/rmi/socket.cpp @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#include "error.h" +#include "socket.h" + +namespace rmi { + +namespace { + +const int MAX_BACKLOG_SIZE = 100; + +void setCloseOnExec(int fd) +{ + if (::fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { + throw SocketException(runtime::GetSystemErrorMessage()); + } +} + +Credentials getCredentials(int fd) +{ + socklen_t length = 256; + char buf[256]; + struct ucred cred; + socklen_t credsz = sizeof(cred); + if (::getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &credsz)) { + throw SocketException(runtime::GetSystemErrorMessage()); + } + + if (::getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buf, &length)) { + throw SocketException(runtime::GetSystemErrorMessage()); + } + + return {cred.pid, cred.uid, cred.gid, buf}; +} + +} // namespace + +Socket::Socket(int fd, bool autoclose) : + socketFd(fd), autoClose(autoclose) +{ +} + +Socket::Socket(Socket&& socket) noexcept : + socketFd(socket.socketFd), + autoClose(socket.autoClose) +{ + socket.socketFd = -1; +} + +Socket::~Socket() noexcept +{ + if ((socketFd != -1) && (autoClose)) { + ::close(socketFd); + } +} + +Socket Socket::accept() +{ + int sockfd = ::accept(socketFd, nullptr, nullptr); + if (sockfd == -1) { + throw SocketException(runtime::GetSystemErrorMessage()); + } + + setCloseOnExec(sockfd); + + return Socket(sockfd); +} + +int Socket::getFd() const +{ + return socketFd; +} + +Credentials Socket::getPeerCredentials() const +{ + return getCredentials(socketFd); +} + +void Socket::read(void *buffer, const size_t size) const +{ + size_t total = 0; + + while (total < size) { + int bytes = ::read(socketFd, reinterpret_cast(buffer) + total, size - total); + if (bytes >= 0) { + total += bytes; + } else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + continue; + } else { + throw SocketException(runtime::GetSystemErrorMessage()); + } + } +} + +void Socket::write(const void *buffer, const size_t size) const +{ + size_t written = 0; + + while (written < size) { + int bytes = ::write(socketFd, reinterpret_cast(buffer) + written, size - written); + if (bytes >= 0) { + written += bytes; + } else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + continue; + } else { + throw SocketException(runtime::GetSystemErrorMessage()); + } + } +} + +void Socket::sendFileDescriptors(const int* fds, const size_t nr) const +{ + if (nr == 0) return; + + int buf; + struct iovec iov = { + .iov_base = &buf, + .iov_len = sizeof(char) + }; + + char buffer[CMSG_SPACE(sizeof(int) * nr)]; + ::memset(buffer, 0, sizeof(buffer)); + + struct msghdr msgh; + ::memset(&msgh, 0, sizeof(msgh)); + + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + msgh.msg_control = buffer; + msgh.msg_controllen = sizeof(buffer); + + struct cmsghdr *cmhp; + cmhp = CMSG_FIRSTHDR(&msgh); + cmhp->cmsg_level = SOL_SOCKET; + cmhp->cmsg_type = SCM_RIGHTS; + cmhp->cmsg_len = CMSG_LEN(sizeof(int) * nr); + + ::memcpy(CMSG_DATA(cmhp), fds, sizeof(int) * nr); + + int written = 0; + while (written < 1) { + ssize_t ret = ::sendmsg(socketFd, &msgh, MSG_NOSIGNAL); + if (ret >= 0) { + written += ret; + } else if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINTR)) { + throw SocketException(runtime::GetSystemErrorMessage()); + } + } +} + +void Socket::receiveFileDescriptors(int* fds, const size_t nr) const +{ + if (nr == 0) return; + + char buf = '!'; + struct iovec iov = { + .iov_base = &buf, + .iov_len = sizeof(char) + }; + + char buffer[CMSG_SPACE(sizeof(int) * nr) + CMSG_SPACE(sizeof(struct ucred))]; + ::memset(buffer, 0, sizeof(buffer)); + + struct msghdr msgh; + ::memset(&msgh, 0, sizeof(msgh)); + + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + msgh.msg_control = buffer; + msgh.msg_controllen = sizeof(buffer); + + ssize_t bytes = 0; + while (bytes < 1) { + ssize_t ret = ::recvmsg(socketFd, &msgh, MSG_WAITALL); + if (ret >= 0) { + bytes += ret; + } else { + if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINTR)) { + throw SocketException(runtime::GetSystemErrorMessage()); + } + } + } + + int i = 0; + for (struct cmsghdr *cmhp = CMSG_FIRSTHDR(&msgh); cmhp != NULL; cmhp = CMSG_NXTHDR(&msgh, cmhp)) { + if ((cmhp->cmsg_level == SOL_SOCKET) && (cmhp->cmsg_type == SCM_RIGHTS)) { + if (cmhp->cmsg_len != CMSG_LEN(sizeof(int) * nr)) { + std::cout << "Invalid File Descriptor Table" << std::endl; + } + + fds[i++] = *(reinterpret_cast(CMSG_DATA(cmhp))); + } + } +} + +#ifdef USE_SYSTEMD_SOCKET_ACTIVATION +int Socket::createSystemdSocket(const std::string& path) +{ + int n = ::sd_listen_fds(-1); + if (n < 0) { + throw SocketException("sd_listen_fds faield"); + } + + for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; ++fd) { + if (::sd_is_socket_unix(fd, SOCK_STREAM, 1, path.c_str(), 0) > 0) { + setCloseOnExec(fd); + return fd; + } + } + + return -1; +} +#endif + +int Socket::createRegularSocket(const std::string& path) +{ + if (path.size() >= sizeof(sockaddr_un::sun_path)) { + throw SocketException(runtime::GetSystemErrorMessage(ENAMETOOLONG)); + } + + int sockfd = ::socket(AF_UNIX, SOCK_STREAM, 0); + if (sockfd == -1) { + throw SocketException(runtime::GetSystemErrorMessage()); + } + + setCloseOnExec(sockfd); + + ::sockaddr_un addr; + addr.sun_family = AF_UNIX; + ::strncpy(addr.sun_path, path.c_str(), sizeof(sockaddr_un::sun_path)); + + if (addr.sun_path[0] == '@') { + addr.sun_path[0] = '\0'; + } else { + unlink(path.c_str()); + } + + if (::bind(sockfd, reinterpret_cast(&addr), sizeof(struct sockaddr_un)) == -1) { + ::close(sockfd); + throw SocketException(runtime::GetSystemErrorMessage()); + } + + int optval = 1; + if (::setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) { + ::close(sockfd); + throw SocketException(runtime::GetSystemErrorMessage()); + } + + if (::listen(sockfd, MAX_BACKLOG_SIZE) == -1) { + ::close(sockfd); + throw SocketException(runtime::GetSystemErrorMessage()); + } + + return sockfd; +} + +Socket Socket::create(const std::string& path) +{ + int fd; + +#ifdef USE_SYSTEMD_SOCKET_ACTIVATION + fd = createSystemdSocket(path); + if (fd == -1) { + fd = createRegularSocket(path); + } +#else + fd = createRegularSocket(path); +#endif + + return Socket(fd); +} + +Socket Socket::connect(const std::string& path) +{ + if (path.size() >= sizeof(sockaddr_un::sun_path)) { + throw SocketException(runtime::GetSystemErrorMessage(ENAMETOOLONG)); + } + + int fd = ::socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) { + throw SocketException(runtime::GetSystemErrorMessage()); + } + + setCloseOnExec(fd); + + sockaddr_un addr; + addr.sun_family = AF_UNIX; + ::strncpy(addr.sun_path, path.c_str(), sizeof(sockaddr_un::sun_path)); + + if (addr.sun_path[0] == '@') { + addr.sun_path[0] = '\0'; + } + + if (::connect(fd, reinterpret_cast(&addr), sizeof(struct sockaddr_un)) == -1) { + ::close(fd); + throw SocketException(runtime::GetSystemErrorMessage()); + } + + return Socket(fd); +} + +} // namespace Ipc diff --git a/common/rmi/socket.h b/common/rmi/socket.h new file mode 100644 index 0000000..09a61bf --- /dev/null +++ b/common/rmi/socket.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RMI_SOCKET_H__ +#define __RMI_SOCKET_H__ + +#include "exception.h" + +namespace rmi { + +class SocketException: public runtime::Exception { +public: + SocketException(const std::string& msg) : runtime::Exception(msg) {} +}; + +struct Credentials { + pid_t pid; + uid_t uid; + gid_t gid; + std::string security; +}; + +class Socket { +public: + explicit Socket(int socketFd = -1, bool autoclose = true); + Socket(Socket&& socket) noexcept; + ~Socket() noexcept; + + Socket(const Socket&) = delete; + Socket& operator=(const Socket&) = delete; + Socket& operator=(Socket&) = delete; + + Socket accept(); + int getFd() const; + Credentials getPeerCredentials() const; + + void write(const void* buffer, const size_t size) const; + void read(void* buffer, const size_t size) const; + + void sendFileDescriptors(const int* fds, const size_t nr) const; + void receiveFileDescriptors(int* fds, const size_t nr) const; + + static Socket create(const std::string& path); + static Socket connect(const std::string& path); + +private: + static int createRegularSocket(const std::string& path); + +#ifdef USE_SYSTEMD_SOCKET_ACTIVATION + static int createSystemdSocket(const std::string& path); +#endif + +private: + int socketFd; + bool autoClose; +}; + +} // namespace rmi +#endif //__RMI_SOCKET_H__ diff --git a/common/serialize.h b/common/serialize.h new file mode 100644 index 0000000..f98dd31 --- /dev/null +++ b/common/serialize.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_SERIALIZER_H__ +#define __RUNTIME_SERIALIZER_H__ + +#include +#include +#include + +#include "reflection.h" + +namespace runtime { + +template +struct SerializableArgument { + SerializableArgument(const T& arg) : + value(arg) + { + } + + const T& value; + REFLECTABLE(value) +}; + +template +struct DeserializableArgument { + DeserializableArgument(T& arg) : + value(arg) + { + } + + T& value; + REFLECTABLE(value) +}; + +template +class Serializer { +public: + Serializer(StorageType& source) : + storage(source) + { + } + + template + void visit(const std::string&, const DataType& value) + { + visitInternal(value); + } + +private: + void visitInternal(const std::string& value) + { + visitInternal(value.size()); + storage.write(value.c_str(), value.size()); + } + + template::value, int>::type = 0> + void visitInternal(const DataType& value) + { + storage.write(&value, sizeof(DataType)); + } + + template::value, int>::type = 0> + void visitInternal(DataType& value) + { + value.accept(*this); + } + + template + void visitInternal(const std::vector& values) + { + visitInternal(values.size()); + for (const DataType& value : values) { + visitInternal(value); + } + } + +private: + StorageType& storage; +}; + +template +class Deserializer { +public: + Deserializer(StorageType& source) : + storage(source) + { + } + + template + void visit(const std::string&, DataType& value) + { + visitInternal(value); + } + +private: + void visitInternal(std::string& value) + { + size_t size; + visitInternal(size); + value.resize(size); + storage.read(&value.front(), size); + } + + template::value, int>::type = 0> + void visitInternal(DataType& value) + { + storage.read(&value, sizeof(DataType)); + } + + template::value, int>::type = 0> + void visitInternal(T& value) + { + value.accept(*this); + } + + template + void visitInternal(std::vector& values) + { + size_t size; + visitInternal(size); + values.resize(size); + + for (DataType& value : values) { + visitInternal(value); + } + } + +private: + StorageType& storage; +}; + +} // namespace runtime + +#endif //__RUNTIME_SERIALIZER_H__ diff --git a/common/thread-pool.cpp b/common/thread-pool.cpp new file mode 100644 index 0000000..bd1e496 --- /dev/null +++ b/common/thread-pool.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include + +#include "thread-pool.h" +#include "exception.h" + +#define __BEGIN_CRITICAL__ { std::unique_lock lock(this->queueMutex); +#define __END_CRITICAL__ } + +namespace runtime { + +ThreadPool::ThreadPool(size_t threads) + : stop(false) +{ + for (size_t i = 0; i < threads; i++) { + workers.emplace_back([this] { + while (true) { + std::function task; + + __BEGIN_CRITICAL__ + condition.wait(lock, [this]{ return stop || !tasks.empty();}); + if (stop && tasks.empty()) { + return; + } + + task = std::move(tasks.front()); + tasks.pop_front(); + __END_CRITICAL__ + + task(); + } + }); + } +} + +ThreadPool::~ThreadPool() +{ + __BEGIN_CRITICAL__ + stop = true; + __END_CRITICAL__ + + condition.notify_all(); + + for (std::thread &worker: workers) { + if (worker.joinable()) { + worker.join(); + } + } +} + +void ThreadPool::submit(std::function&& task) +{ + __BEGIN_CRITICAL__ + if (!stop) { + tasks.push_back(std::move(task)); + } + __END_CRITICAL__ + + condition.notify_one(); +} + +} // namespace runtime diff --git a/libs/dpm/array.h b/common/thread-pool.h similarity index 58% rename from libs/dpm/array.h rename to common/thread-pool.h index 77ac2a3..e00e4cf 100644 --- a/libs/dpm/array.h +++ b/common/thread-pool.h @@ -14,46 +14,34 @@ * limitations under the License */ -#ifndef __RUNTIME_ARRAY_H__ -#define __RUNTIME_ARRAY_H__ +#ifndef __RUNTIME_THREAD_POOL_H__ +#define __RUNTIME_THREAD_POOL_H__ +#include +#include +#include +#include #include -#include +#include namespace runtime { -template -class Array final { +class ThreadPool { public: - Array() = delete; - Array(std::vector &&list) : - list(std::move(list)), it(this->list.begin()) - { - } - - Array(const std::vector &list) : - list(list), it(this->list.begin()) - { - } - - T *next() - { - if (it != list.end()) { - return &(*it++); - } - return NULL; - } - - bool isEnd() - { - return it == list.end(); - } + ThreadPool(size_t threads); + ~ThreadPool(); + + void submit(std::function&& task); private: - std::vector list; - typename std::vector::iterator it; + std::vector workers; + std::deque> tasks; + + std::mutex queueMutex; + std::condition_variable condition; + bool stop; }; } // namespace runtime -#endif // __RUNTIME_ARRAY_H__ +#endif //__RUNTIME_THREAD_POOL_H__ diff --git a/common/xml/document.cpp b/common/xml/document.cpp new file mode 100644 index 0000000..f83fd2f --- /dev/null +++ b/common/xml/document.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +#include "document.h" +#include "keepblanks.h" + +#include "exception.h" +#include "audit/logger.h" + +namespace xml { + +Document::Document(const std::string& root, const std::string& version) : + implementation(xmlNewDoc((const xmlChar*)version.c_str())) +{ + if (implementation == nullptr) { + throw runtime::Exception("Failed to create document"); + } + + implementation->_private = this; + + xmlNode* rootPtr = xmlNewNode(NULL, xmlStrdup((const xmlChar*)root.c_str())); + xmlDocSetRootElement(implementation, rootPtr); + + rootNode = new Node(rootPtr); +} + +Document::Document(xmlDoc* doc) + : implementation(doc) +{ + implementation->_private = this; + + rootNode = new Node(xmlDocGetRootElement(implementation)); +} + +Document::~Document() +{ + if (rootNode != nullptr) { + delete rootNode; + } + + xmlFreeDoc(implementation); +} + +Node& Document::getRootNode() +{ + if (rootNode == nullptr) { + throw runtime::Exception("Empty document"); + } + + return *rootNode; +} + +Node::NodeList Document::evaluate(const std::string& xpath) +{ + auto ctxt = xmlXPathNewContext(implementation); + if (ctxt == nullptr) { + throw runtime::Exception("Failed to create XPath context for " + xpath); + } + + auto result = xmlXPathEval((const xmlChar*)xpath.c_str(), ctxt); + if (result == nullptr) { + xmlXPathFreeContext(ctxt); + throw runtime::Exception("Invalid XPath: " + xpath); + } + + if (result ->type != XPATH_NODESET) { + xmlXPathFreeObject(result); + xmlXPathFreeContext(ctxt); + + throw runtime::Exception("Only nodeset result types are supported"); + } + + auto nodeset = result->nodesetval; + + Node::NodeList nodes; + if ((nodeset == nullptr) || (xmlXPathNodeSetIsEmpty(nodeset))) { + xmlXPathFreeContext(ctxt); + return nodes; + } + + const int count = xmlXPathNodeSetGetLength(nodeset); + + nodes.reserve(count); + for (int i = 0; i != count; i++) { + auto cnode = xmlXPathNodeSetItem(nodeset, i); + if (!cnode) { + continue; + } + + if (cnode->type == XML_NAMESPACE_DECL) { + continue; + } + + nodes.emplace_back(cnode); + } + + xmlXPathFreeObject(result); + xmlXPathFreeContext(ctxt); + + return nodes; +} + +void Document::write(const std::string& filename, const std::string& encoding, bool formatted) +{ + KeepBlanks keepBlanks(KeepBlanks::Default); + xmlIndentTreeOutput = formatted; + + xmlResetLastError(); + + const int result = xmlSaveFormatFileEnc(filename.c_str(), + implementation, + encoding.c_str(), + formatted); + if (result == 0) { + throw runtime::Exception("Failed to write XML document"); + } +} + +} // namespace xml diff --git a/common/xml/document.h b/common/xml/document.h new file mode 100644 index 0000000..a5bdc93 --- /dev/null +++ b/common/xml/document.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __XML_DOCUMENT_H__ +#define __XML_DOCUMENT_H__ + +#include +#include + +#include +#include +#include + +#include "node.h" + +namespace xml { + +class Document { +public: + Document(const std::string& root, const std::string& version = XML_DEFAULT_VERSION); + Document(xmlDoc* doc); + + ~Document(); + + Node& getRootNode(); + + Node::NodeList evaluate(const std::string& xpath); + void write(const std::string& filename, const std::string& encoding, bool formatted); + +private: + Node* rootNode; + xmlDoc* implementation; +}; + +} // namespace xml +#endif //__XML_DOCUMENT_H__ diff --git a/common/xml/keepblanks.cpp b/common/xml/keepblanks.cpp new file mode 100644 index 0000000..3c38e0a --- /dev/null +++ b/common/xml/keepblanks.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "keepblanks.h" + +namespace xml { + +KeepBlanks::KeepBlanks(bool value) +{ + preservedIndentTreeOutput = xmlIndentTreeOutput; + preservedKeepBlanksDefault = xmlKeepBlanksDefault(value ? 1 : 0); +} + +KeepBlanks::~KeepBlanks() +{ + xmlKeepBlanksDefault(preservedKeepBlanksDefault); + xmlIndentTreeOutput = preservedIndentTreeOutput; +} + +} // namespace xml diff --git a/common/xml/keepblanks.h b/common/xml/keepblanks.h new file mode 100644 index 0000000..7d5c2f4 --- /dev/null +++ b/common/xml/keepblanks.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __XML_KEEPBLANKS_H__ +#define __XML_KEEPBLANKS_H__ + +#include + +namespace xml { + +class KeepBlanks { +public: + KeepBlanks(bool value); + ~KeepBlanks(); + + static const bool Default = true; + +private: + int preservedKeepBlanksDefault; + int preservedIndentTreeOutput; +}; + +} // namespace xml +#endif //__XML_KEEPBLANKS_H__ diff --git a/common/xml/node.cpp b/common/xml/node.cpp new file mode 100644 index 0000000..0d0c255 --- /dev/null +++ b/common/xml/node.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "node.h" + +#include "exception.h" + +namespace xml { + +Node::Node(xmlNode* node) : + implementation(node) +{ +} + +Node::Node(Node&& node) : + implementation(node.implementation) +{ +} + +Node::~Node() +{ +} + +Node::NodeList Node::getChildren() const +{ + NodeList nodeList; + + auto child = implementation->xmlChildrenNode; + while (child != nullptr) { + nodeList.emplace_back(child); + child = child->next; + } + + return nodeList; +} + +Node Node::addNewChild(const std::string& name) +{ + xmlNode* nodePtr = xmlNewNode(NULL, xmlStrdup((const xmlChar*)name.c_str())); + if (nodePtr == nullptr) { + throw runtime::Exception("Can not create a new node"); + } + xmlAddChild(implementation, nodePtr); + + return Node(nodePtr); +} + +std::string Node::getName() const +{ + return implementation->name ? (const char*)implementation->name : ""; +} + +void Node::setName(const std::string& name) +{ + xmlNodeSetName(implementation, (const xmlChar*)name.c_str()); +} + +std::string Node::getContent() const +{ + xmlChar* content = xmlNodeGetContent(implementation); + if (content == NULL) { + return ""; + } + std::string ret((const char*)content); + xmlFree(content); + return ret; +} + +void Node::setContent(const std::string& content) +{ + xmlNodeSetContent(implementation, (xmlChar*)content.c_str()); +} + +std::string Node::getProp(const std::string& name) const +{ + if (implementation->type != XML_ELEMENT_NODE) { + throw runtime::Exception("This node type does not have properties"); + } + + xmlChar* prop = xmlGetProp(implementation, (xmlChar*)name.c_str()); + if (prop) { + std::string ret((const char*)prop); + xmlFree(prop); + return ret; + } + + return ""; +} + +void Node::setProp(const std::string& name, const std::string& val) +{ + if (implementation->type != XML_ELEMENT_NODE) { + throw runtime::Exception("Can not set properties for this node type"); + } + + xmlSetProp(implementation, (xmlChar*)name.c_str(), (xmlChar*)val.c_str()); +} + +bool Node::isBlank() const +{ + return xmlIsBlankNode(const_cast(implementation)); +} + +} // namespace xml diff --git a/common/xml/node.h b/common/xml/node.h new file mode 100644 index 0000000..755d170 --- /dev/null +++ b/common/xml/node.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __XML_NODE_H__ +#define __XML_NODE_H__ + +#include +#include +#include +#include + +#include +#include + +namespace xml { + +class Node { +public: + typedef std::vector NodeList; + + explicit Node(xmlNode* node); + Node(Node&&); + Node(const Node&) = delete; + + ~Node(); + + Node& operator=(const Node&) = delete; + + NodeList getChildren() const; + Node addNewChild(const std::string& name); + + std::string getName() const; + void setName(const std::string& name); + + std::string getContent() const; + void setContent(const std::string& content); + + std::string getProp(const std::string& name) const; + void setProp(const std::string& name, const std::string& val); + + bool isBlank() const; + +private: + xmlNode* implementation; +}; + +} // namespace xml +#endif //__XML_NODE_H__ diff --git a/common/xml/parser.cpp b/common/xml/parser.cpp new file mode 100644 index 0000000..91c8d42 --- /dev/null +++ b/common/xml/parser.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +#include + +#include "parser.h" +#include "keepblanks.h" + +#include "exception.h" + +namespace xml { + +Document* Parser::parseContext(xmlParserCtxt* context, bool validate) +{ + if (context == nullptr) { + throw runtime::Exception("Could not create parser context"); + } + + KeepBlanks(false); + + int options = 0; + + if (validate) { + options |= XML_PARSE_DTDVALID; + } else { + options &= ~XML_PARSE_DTDVALID; + } + + xmlCtxtUseOptions(context, options); + + if (xmlParseDocument(context) < 0) { + xmlFreeParserCtxt(context); + throw runtime::Exception("Parsing failed"); + } + + xmlDoc* document = context->myDoc; + + // We took the ownership on the doc + context->myDoc = nullptr; + + xmlFreeParserCtxt(context); + + return new Document(document); +} + +Document* Parser::parseFile(const std::string& filename, bool validate) +{ + xmlParserCtxt* context = xmlCreateFileParserCtxt(filename.c_str()); + if (context == nullptr) { + throw runtime::Exception("Could not create parser context"); + } + + if (context->directory == nullptr) { + context->directory = xmlParserGetDirectory(filename.c_str()); + } + + return parseContext(context, validate); +} + +Document* Parser::parseString(const std::string& xml, bool validate) +{ + xmlParserCtxt* context = xmlCreateMemoryParserCtxt(xml.c_str(), xml.size() + 1); + + if (context == nullptr) { + throw runtime::Exception("Could not create parser context"); + } + + return parseContext(context, validate); +} + +} // namespace xml diff --git a/common/xml/parser.h b/common/xml/parser.h new file mode 100644 index 0000000..87b76dc --- /dev/null +++ b/common/xml/parser.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __XML_DOMPARSER_H__ +#define __XML_DOMPARSER_H__ + +#include + +#include +#include + +#include "document.h" + +namespace xml { + +class Parser { +public: + static Document* parseFile(const std::string& filename, bool validate = false); + static Document* parseString(const std::string& xml, bool validate = false); + +private: + static Document* parseContext(xmlParserCtxt* context, bool validate = false); +}; + +} // namespace xml +#endif //__XML_DOMPARSER_H__ diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index 3536ff4..28c3602 100755 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -59,13 +59,8 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-fvisibility=hid SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${LIB_SOVERSION}) SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${LIB_VERSION}) -PKG_CHECK_MODULES(LIBS_DEPS REQUIRED - klay - glib-2.0 -) - -INCLUDE_DIRECTORIES(SYSTEM ${LIBS_DEPS_INCLUDE_DIRS} ${DPM_POLICY} ${DPM_LIBS}) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LIBS_DEPS_LIBRARIES} pthread) +INCLUDE_DIRECTORIES(SYSTEM ${DPM_COMMON} ${DPM_POLICY} ${DPM_LIBS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthread dpm-common) CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_BINARY_DIR}/${PC_FILE} @ONLY) diff --git a/libs/bluetooth.cpp b/libs/bluetooth.cpp index 73caa08..b9b6c52 100644 --- a/libs/bluetooth.cpp +++ b/libs/bluetooth.cpp @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License */ + #include "bluetooth.hxx" +#include "audit/logger.h" namespace DevicePolicyManager { diff --git a/libs/dpm/client-handle.cpp b/libs/dpm/client-handle.cpp index 5cb021d..124083a 100644 --- a/libs/dpm/client-handle.cpp +++ b/libs/dpm/client-handle.cpp @@ -21,6 +21,8 @@ #include "policy-client.h" #include "debug.h" +#include "exception.h" + DevicePolicyContext& GetDevicePolicyContext(void* handle) { assert(handle); diff --git a/libs/location.cpp b/libs/location.cpp index 2134b05..cca4474 100644 --- a/libs/location.cpp +++ b/libs/location.cpp @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License */ + #include "location.hxx" +#include "audit/logger.h" namespace DevicePolicyManager { diff --git a/libs/password.cpp b/libs/password.cpp index c6950a1..4dbc778 100644 --- a/libs/password.cpp +++ b/libs/password.cpp @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License */ + #include "password.hxx" +#include "audit/logger.h" namespace DevicePolicyManager { diff --git a/libs/policy-client.cpp b/libs/policy-client.cpp index ce7dc9c..e9356a3 100644 --- a/libs/policy-client.cpp +++ b/libs/policy-client.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License */ + #include "policy-client.h" namespace { diff --git a/libs/policy-client.h b/libs/policy-client.h index f91caa5..c1ac082 100644 --- a/libs/policy-client.h +++ b/libs/policy-client.h @@ -21,7 +21,7 @@ #include #include -#include +#include "rmi/client.h" typedef std::function PolicyChangeListener; typedef std::function SignalListener; diff --git a/libs/restriction.cpp b/libs/restriction.cpp index 307c597..b52580a 100644 --- a/libs/restriction.cpp +++ b/libs/restriction.cpp @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License */ + #include "restriction.hxx" +#include "audit/logger.h" namespace DevicePolicyManager { diff --git a/libs/security.cpp b/libs/security.cpp index 1dd8e7e..733821a 100644 --- a/libs/security.cpp +++ b/libs/security.cpp @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License */ + #include "security.hxx" +#include "audit/logger.h" namespace DevicePolicyManager { diff --git a/libs/storage.cpp b/libs/storage.cpp index bd1a928..d49769f 100644 --- a/libs/storage.cpp +++ b/libs/storage.cpp @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License */ + +#include "policy-client.h" + #include "storage.hxx" namespace DevicePolicyManager { diff --git a/libs/wifi.cpp b/libs/wifi.cpp index fb81e13..bc3c6c0 100644 --- a/libs/wifi.cpp +++ b/libs/wifi.cpp @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License */ + #include "wifi.hxx" +#include "audit/logger.h" namespace DevicePolicyManager { diff --git a/libs/zone.cpp b/libs/zone.cpp index 212aefb..4f0768b 100644 --- a/libs/zone.cpp +++ b/libs/zone.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License */ + #include "zone.hxx" namespace DevicePolicyManager { diff --git a/measure.sh b/measure.sh index 2b9d7de..e171a91 100755 --- a/measure.sh +++ b/measure.sh @@ -3,5 +3,12 @@ lcov -c -d device-policy-manager-0.0.1/server/CMakeFiles/device-policy-manager.dir \ -d device-policy-manager-0.0.1/libs/CMakeFiles/dpm.dir \ -d device-policy-manager-0.0.1/libs/CMakeFiles/dpm.dir/dpm \ + -d device-policy-manager-0.0.1/common/CMakeFiles/dpm-common.dir \ + -d device-policy-manager-0.0.1/common/CMakeFiles/dpm-common.dir/audit \ + -d device-policy-manager-0.0.1/common/CMakeFiles/dpm-common.dir/db \ + -d device-policy-manager-0.0.1/common/CMakeFiles/dpm-common.dir/auth \ + -d device-policy-manager-0.0.1/common/CMakeFiles/dpm-common.dir/xml \ + -d device-policy-manager-0.0.1/common/CMakeFiles/dpm-common.dir/dbus \ + -d device-policy-manager-0.0.1/common/CMakeFiles/dpm-common.dir/rmi \ -o info genhtml info -o out diff --git a/packaging/device-policy-manager.spec b/packaging/device-policy-manager.spec index 323d427..e08689b 100755 --- a/packaging/device-policy-manager.spec +++ b/packaging/device-policy-manager.spec @@ -9,7 +9,6 @@ BuildRequires: gcc BuildRequires: cmake BuildRequires: pam-devel BuildRequires: gettext-tools -BuildRequires: pkgconfig(klay) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(libxml-2.0) BuildRequires: pkgconfig(sqlite3) @@ -148,7 +147,12 @@ Testcases for device policy manager and device policy client %files -n dpm-testcases %defattr(644,root,root,755) +%attr(755,root,root) %{_bindir}/dpm-unit-tests %attr(755,root,root) %{_bindir}/dpm-api-tests +%defattr(-,root,root,-) +%{TZ_SYS_DATA}/dpm/sample-policy.xml +%defattr(755,root,root,755) +%{TZ_SYS_DATA}/dpm/unittest-proc.sh ## Tools Package ############################################################# %package -n org.tizen.ode diff --git a/policy/administration.hxx b/policy/administration.hxx index 564a434..f6ed25a 100644 --- a/policy/administration.hxx +++ b/policy/administration.hxx @@ -17,6 +17,9 @@ #ifndef __ADMINISTRATION_POLICY__ #define __ADMINISTRATION_POLICY__ +#include + +#include "data-type.h" #include "policy-context.hxx" namespace DevicePolicyManager { diff --git a/policy/application.hxx b/policy/application.hxx index a6ef8a1..ca50eac 100644 --- a/policy/application.hxx +++ b/policy/application.hxx @@ -17,6 +17,7 @@ #ifndef __APPLICATION_POLICY__ #define __APPLICATION_POLICY__ +#include "data-type.h" #include "policy-context.hxx" namespace DevicePolicyManager { diff --git a/policy/bluetooth.hxx b/policy/bluetooth.hxx index c810ae2..3d5a23f 100644 --- a/policy/bluetooth.hxx +++ b/policy/bluetooth.hxx @@ -17,6 +17,7 @@ #ifndef __BLUETOOTH_POLICY__ #define __BLUETOOTH_POLICY__ +#include "data-type.h" #include "policy-context.hxx" namespace DevicePolicyManager { diff --git a/policy/location.hxx b/policy/location.hxx index 306049a..c401d57 100644 --- a/policy/location.hxx +++ b/policy/location.hxx @@ -17,6 +17,7 @@ #ifndef __LOCATION_POLICY__ #define __LOCATION_POLICY__ +#include "data-type.h" #include "policy-context.hxx" namespace DevicePolicyManager { diff --git a/policy/password.hxx b/policy/password.hxx index ccb5454..cd1a59b 100644 --- a/policy/password.hxx +++ b/policy/password.hxx @@ -17,6 +17,7 @@ #ifndef __PASSWORD_POLICY__ #define __PASSWORD_POLICY__ +#include "data-type.h" #include "policy-context.hxx" namespace DevicePolicyManager { diff --git a/policy/restriction.hxx b/policy/restriction.hxx index ffaba33..ffb6a31 100644 --- a/policy/restriction.hxx +++ b/policy/restriction.hxx @@ -17,6 +17,7 @@ #ifndef __RESTRICTION_POLICY__ #define __RESTRICTION_POLICY__ +#include "data-type.h" #include "policy-context.hxx" namespace DevicePolicyManager diff --git a/policy/security.hxx b/policy/security.hxx index 4da3cbe..6a539f1 100644 --- a/policy/security.hxx +++ b/policy/security.hxx @@ -17,6 +17,7 @@ #ifndef __SECURITY_POLICY__ #define __SECURITY_POLICY__ +#include "data-type.h" #include "policy-context.hxx" namespace DevicePolicyManager { diff --git a/policy/storage.hxx b/policy/storage.hxx index 6647fd9..89181dc 100644 --- a/policy/storage.hxx +++ b/policy/storage.hxx @@ -17,6 +17,7 @@ #ifndef __STORAGE_POLICY__ #define __STORAGE_POLICY__ +#include "data-type.h" #include "policy-context.hxx" namespace DevicePolicyManager { diff --git a/policy/wifi.hxx b/policy/wifi.hxx index 4155db5..94e88f8 100644 --- a/policy/wifi.hxx +++ b/policy/wifi.hxx @@ -17,6 +17,7 @@ #ifndef __WIFI_POLICY__ #define __WIFI_POLICY__ +#include "data-type.h" #include "policy-context.hxx" namespace DevicePolicyManager { diff --git a/policy/zone.hxx b/policy/zone.hxx index 848f929..6c68c5c 100644 --- a/policy/zone.hxx +++ b/policy/zone.hxx @@ -17,6 +17,7 @@ #ifndef __ZONE_POLICY__ #define __ZONE_POLICY__ +#include "data-type.h" #include "policy-context.hxx" namespace DevicePolicyManager { diff --git a/policy/zone/app-proxy.hxx b/policy/zone/app-proxy.hxx index 1339499..0cec21a 100644 --- a/policy/zone/app-proxy.hxx +++ b/policy/zone/app-proxy.hxx @@ -17,6 +17,7 @@ #ifndef __ZONE_APP_PROXY__ #define __ZONE_APP_PROXY__ +#include "data-type.h" #include "policy-context.hxx" namespace DevicePolicyManager { diff --git a/policy/zone/package-proxy.hxx b/policy/zone/package-proxy.hxx index f397d97..b7405e3 100644 --- a/policy/zone/package-proxy.hxx +++ b/policy/zone/package-proxy.hxx @@ -17,6 +17,7 @@ #ifndef __ZONE_PACKAGE_PROXY__ #define __ZONE_PACKAGE_PROXY__ +#include "data-type.h" #include "policy-context.hxx" namespace DevicePolicyManager { diff --git a/policy/zone/zone.hxx b/policy/zone/zone.hxx index 3612e0f..2f78489 100644 --- a/policy/zone/zone.hxx +++ b/policy/zone/zone.hxx @@ -17,6 +17,7 @@ #ifndef __ZONE_MANAGER__ #define __ZONE_MANAGER__ +#include "data-type.h" #include "policy-context.hxx" namespace DevicePolicyManager { diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index b81e16a..a7d32eb 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -37,9 +37,6 @@ SET(POLICY administration.cpp SET(DEPENDENCY glib-2.0 gio-2.0 - klay - libxml-2.0 - sqlite3 bundle aul appsvc @@ -68,9 +65,9 @@ ADD_EXECUTABLE(${TARGET} ${FOUNDATION} ${POLICY}) PKG_CHECK_MODULES(SERVER_DEPS REQUIRED ${DEPENDENCY}) -INCLUDE_DIRECTORIES(SYSTEM ${SERVER_DEPS_INCLUDE_DIRS} ${DPM_POLICY} ${DPM_SERVER}) +INCLUDE_DIRECTORIES(SYSTEM ${SERVER_DEPS_INCLUDE_DIRS} ${DPM_COMMON} ${DPM_POLICY} ${DPM_SERVER}) -TARGET_LINK_LIBRARIES(${TARGET} ${SERVER_DEPS_LIBRARIES} pthread sqlite3) +TARGET_LINK_LIBRARIES(${TARGET} ${SERVER_DEPS_LIBRARIES} pthread dpm-common) SET_TARGET_PROPERTIES(${TARGET} PROPERTIES COMPILE_FLAGS "-fPIE") SET_TARGET_PROPERTIES(${TARGET} PROPERTIES LINK_FLAGS "-pie") diff --git a/server/administration.cpp b/server/administration.cpp index 53f9d00..e47d3c4 100644 --- a/server/administration.cpp +++ b/server/administration.cpp @@ -13,13 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License */ -#include -#include + +#include "administration.hxx" #include "policy-builder.h" #include "client-manager.h" - -#include "administration.hxx" +#include "audit/logger.h" namespace DevicePolicyManager { diff --git a/server/app-bundle.cpp b/server/app-bundle.cpp index 518e36f..0c253d3 100644 --- a/server/app-bundle.cpp +++ b/server/app-bundle.cpp @@ -13,12 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License */ -#include - -#include #include "app-bundle.h" +#include "error.h" +#include "exception.h" +#include "audit/logger.h" + Bundle::Bundle() : handle(nullptr) { diff --git a/server/app-bundle.h b/server/app-bundle.h index df01979..887f2a0 100644 --- a/server/app-bundle.h +++ b/server/app-bundle.h @@ -22,6 +22,8 @@ #include +#include "exception.h" + class Bundle { public: Bundle(); diff --git a/server/application.cpp b/server/application.cpp index 4ed4a1b..c3b6731 100644 --- a/server/application.cpp +++ b/server/application.cpp @@ -21,14 +21,13 @@ #include #include -#include -#include +#include "application.hxx" + +#include "policy-builder.h" #include "packman.h" #include "launchpad.h" -#include "policy-builder.h" - -#include "application.hxx" +#include "audit/logger.h" namespace DevicePolicyManager { diff --git a/server/bluetooth.cpp b/server/bluetooth.cpp index 5e4d505..0ffdc06 100644 --- a/server/bluetooth.cpp +++ b/server/bluetooth.cpp @@ -15,16 +15,16 @@ */ #include -#include #include -#include -#include -#include +#include + +#include "bluetooth.hxx" +#include "restriction.hxx" #include "privilege.h" #include "policy-builder.h" - -#include "bluetooth.hxx" +#include "audit/logger.h" +#include "dbus/connection.h" #define POLICY_ENFORCING_FAILED(ret) \ (((ret) == BLUETOOTH_DPM_RESULT_ACCESS_DENIED) || \ diff --git a/server/client-manager.cpp b/server/client-manager.cpp index 9614308..46e07a2 100644 --- a/server/client-manager.cpp +++ b/server/client-manager.cpp @@ -14,14 +14,17 @@ * limitations under the License */ -#include #include +#include #include -#include +#include +#include +#include "client-manager.h" #include "policy.h" -#include "client-manager.h" +#include "exception.h" +#include "audit/logger.h" namespace { diff --git a/server/client-manager.h b/server/client-manager.h index 33fc401..395ff96 100644 --- a/server/client-manager.h +++ b/server/client-manager.h @@ -22,13 +22,13 @@ #include #include -#include -#include -#include - #include "policy.h" #include "policy-storage.h" +#include "db/connection.h" +#include "db/statement.h" +#include "db/column.h" + class Client { public: Client(const Client&) = delete; diff --git a/server/launchpad.cpp b/server/launchpad.cpp index d0a1dbf..272261f 100644 --- a/server/launchpad.cpp +++ b/server/launchpad.cpp @@ -13,16 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License */ + +#include #include #include -#include #include -#include -#include #include "launchpad.h" +#include "error.h" +#include "exception.h" +#include "audit/logger.h" +#include "dbus/variant.h" +#include "dbus/connection.h" + Launchpad::Launchpad(const uid_t uid) : user(uid) { diff --git a/server/launchpad.h b/server/launchpad.h index e5d3ceb..2435f35 100644 --- a/server/launchpad.h +++ b/server/launchpad.h @@ -20,6 +20,7 @@ #include #include "app-bundle.h" +#include "exception.h" class Launchpad { public: diff --git a/server/location.cpp b/server/location.cpp index 786f7d8..a3d4b5c 100644 --- a/server/location.cpp +++ b/server/location.cpp @@ -16,10 +16,11 @@ #include +#include "location.hxx" + #include "privilege.h" #include "policy-builder.h" - -#include "location.hxx" +#include "audit/logger.h" namespace DevicePolicyManager { diff --git a/server/main.cpp b/server/main.cpp index 1ec6cb2..448df58 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -13,14 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License */ + +#include +#include #include #include #include +#include #include -#include -#include -#include #include #include diff --git a/server/packman.cpp b/server/packman.cpp index 8739dce..834da17 100644 --- a/server/packman.cpp +++ b/server/packman.cpp @@ -13,10 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License */ -#include -#include + +#include +#include + +#include #include "packman.h" +#include "exception.h" +#include "audit/logger.h" namespace { diff --git a/server/packman.h b/server/packman.h index 9211fcc..95d4075 100644 --- a/server/packman.h +++ b/server/packman.h @@ -17,11 +17,10 @@ #ifndef __DPM_PACKMAN_H__ #define __DPM_PACKMAN_H__ -#include #include +#include #include -#include #include #include diff --git a/server/password.cpp b/server/password.cpp index 4dd8c5c..facb447 100644 --- a/server/password.cpp +++ b/server/password.cpp @@ -16,20 +16,20 @@ #include -#include -#include +#include #include +#include #include +#include #include -#include -#include -#include - -#include "privilege.h" -#include "policy-builder.h" #include "password.hxx" +#include "policy-builder.h" +#include "privilege.h" +#include "auth/user.h" +#include "audit/logger.h" + #define SIMPLE_PASSWORD_LENGTH 4 #define PASSWORD_EMPTY_STRING "\\n" diff --git a/server/policy-storage.cpp b/server/policy-storage.cpp index 10b66a0..20aaa96 100644 --- a/server/policy-storage.cpp +++ b/server/policy-storage.cpp @@ -14,17 +14,17 @@ * limitations under the License */ -#include -#include #include +#include +#include -#include -#include -#include -#include +#include "policy-context.hxx" #include "policy-storage.h" -#include "policy-context.hxx" + +#include "error.h" +#include "exception.h" +#include "audit/logger.h" namespace { diff --git a/server/policy-storage.h b/server/policy-storage.h index 4a0ef39..d0e5f7c 100644 --- a/server/policy-storage.h +++ b/server/policy-storage.h @@ -23,7 +23,9 @@ #include "policy.h" -#include +#include "xml/parser.h" +#include "xml/document.h" +#include "xml/node.h" class PolicyStorage { public: diff --git a/server/policy.h b/server/policy.h index 625248c..042843d 100644 --- a/server/policy.h +++ b/server/policy.h @@ -21,7 +21,8 @@ #include #include -#include +#include "xml/document.h" +#include "xml/node.h" class Policy { public: diff --git a/server/restriction.cpp b/server/restriction.cpp index 2440a34..14c5929 100644 --- a/server/restriction.cpp +++ b/server/restriction.cpp @@ -15,14 +15,13 @@ */ #include -#include -#include -#include + +#include "restriction.hxx" #include "privilege.h" #include "policy-builder.h" - -#include "restriction.hxx" +#include "audit/logger.h" +#include "dbus/connection.h" #define PULSEAUDIO_LOGIN_INTERFACE \ "org.pulseaudio.Server", \ diff --git a/server/security.cpp b/server/security.cpp index d35aaad..bb795b1 100755 --- a/server/security.cpp +++ b/server/security.cpp @@ -26,15 +26,15 @@ #include #include #include -#include -#include -#include + +#include "security.hxx" #include "privilege.h" #include "policy-builder.h" #include "launchpad.h" - -#include "security.hxx" +#include "process.h" +#include "filesystem.h" +#include "audit/logger.h" namespace DevicePolicyManager { diff --git a/server/server.cpp b/server/server.cpp index ab476bf..4ba4caa 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -37,7 +37,7 @@ Server::Server() service->setPrivilegeChecker(std::bind(&Server::checkPeerPrivilege, this, _1, _2)); - service->registerParametricMethod(this, "", (runtime::FileDescriptor)(Server::registerNotificationSubscriber)(std::string)); + service->registerParametricMethod(this, "", (FileDescriptor)(Server::registerNotificationSubscriber)(std::string)); service->registerParametricMethod(this, "", (int)(Server::unregisterNotificationSubscriber)(std::string, int)); } @@ -58,9 +58,9 @@ void Server::terminate() service->stop(); } -runtime::FileDescriptor Server::registerNotificationSubscriber(const std::string& name) +FileDescriptor Server::registerNotificationSubscriber(const std::string& name) { - return runtime::FileDescriptor(service->subscribeNotification(name), true); + return FileDescriptor(service->subscribeNotification(name), true); } int Server::unregisterNotificationSubscriber(const std::string& name, int id) diff --git a/server/server.h b/server/server.h index 9613a52..224b93a 100644 --- a/server/server.h +++ b/server/server.h @@ -20,12 +20,12 @@ #include #include -#include -#include -#include - #include "policy-storage.h" +#include "file-descriptor.h" +#include "filesystem.h" +#include "rmi/service.h" + class Server { public: Server(); @@ -72,7 +72,7 @@ public: const std::string& event, const std::string& info); std::string getPolicy(const std::string& name) const; - runtime::FileDescriptor registerNotificationSubscriber(const std::string& name); + FileDescriptor registerNotificationSubscriber(const std::string& name); int unregisterNotificationSubscriber(const std::string& name, int id); bool checkPeerPrivilege(const rmi::Credentials& cred, const std::string& privilege); diff --git a/server/storage.cpp b/server/storage.cpp index ef37d56..6d4dcea 100644 --- a/server/storage.cpp +++ b/server/storage.cpp @@ -13,21 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License */ + + #include + #include + #include -#include -#include -#include -#include -#include -#include -#include -#include +#include "storage.hxx" #include "privilege.h" #include "policy-builder.h" - -#include "storage.hxx" +#include "exception.h" +#include "process.h" +#include "filesystem.h" +#include "dbus/connection.h" +#include "dbus/variant.h" +#include "audit/logger.h" namespace DevicePolicyManager { diff --git a/server/wifi.cpp b/server/wifi.cpp index c0ddd24..4b388dd 100644 --- a/server/wifi.cpp +++ b/server/wifi.cpp @@ -14,23 +14,24 @@ * limitations under the License */ +#include #include #include #include #include #include -#include #include -#include -#include -#include +#include + +#include "wifi.hxx" #include "privilege.h" -#include "app-bundle.h" #include "policy-builder.h" -#include "wifi.hxx" +#include "app-bundle.h" +#include "audit/logger.h" +#include "dbus/connection.h" #define NETCONFIG_INTERFACE \ "net.netconfig", \ diff --git a/server/zone.cpp b/server/zone.cpp index 0e74363..bf8649d 100755 --- a/server/zone.cpp +++ b/server/zone.cpp @@ -22,15 +22,17 @@ #include #include -#include -#include #include "zone.hxx" #include "zone/zone.hxx" -#include "launchpad.h" #include "privilege.h" #include "policy-builder.h" +#include "error.h" +#include "launchpad.h" +#include "filesystem.h" +#include "auth/user.h" +#include "audit/logger.h" #define NAME_PATTERN "^[A-Za-z_][A-Za-z0-9_.-]*" diff --git a/server/zone/app-proxy.cpp b/server/zone/app-proxy.cpp index 48a400d..841e11a 100644 --- a/server/zone/app-proxy.cpp +++ b/server/zone/app-proxy.cpp @@ -16,18 +16,18 @@ #include #include +#include #include -#include -#include -#include +#include "zone/app-proxy.hxx" +#include "policy-builder.h" +#include "error.h" #include "packman.h" #include "launchpad.h" -#include "policy-builder.h" - -#include "zone/app-proxy.hxx" +#include "auth/user.h" +#include "audit/logger.h" namespace DevicePolicyManager { diff --git a/server/zone/package-proxy.cpp b/server/zone/package-proxy.cpp index 63d6389..2daeea1 100644 --- a/server/zone/package-proxy.cpp +++ b/server/zone/package-proxy.cpp @@ -15,15 +15,14 @@ */ #include #include - #include -#include -#include - -#include "packman.h" -#include "policy-builder.h" #include "zone/package-proxy.hxx" +#include "policy-builder.h" +#include "error.h" +#include "packman.h" +#include "auth/user.h" +#include "audit/logger.h" namespace DevicePolicyManager { diff --git a/server/zone/zone.cpp b/server/zone/zone.cpp index c71d8c6..077edc1 100644 --- a/server/zone/zone.cpp +++ b/server/zone/zone.cpp @@ -20,26 +20,25 @@ #include +#include +#include #include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "zone/zone.hxx" +#include "policy-builder.h" +#include "error.h" +#include "process.h" #include "packman.h" #include "launchpad.h" -#include "policy-builder.h" - -#include "zone/zone.hxx" +#include "filesystem.h" +#include "auth/user.h" +#include "xml/parser.h" +#include "xml/document.h" +#include "audit/logger.h" +#include "dbus/connection.h" #define ZONE_DELEGATOR_APP "org.tizen.keyguard" #define NOTIFICATION_SUB_ICON_PATH DATA_PATH "/zone_noti_list_sub_icon.png" diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 59da9d6..ddaab5c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -13,26 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. # -SET(API_TEST_TARGET "dpm-api-tests") -SET(API_TEST_SOURCES main.c - testbench.c - admin.c - application.c - context.c - bluetooth.c - manager.c - restriction.c - security.c - wifi.c -) +SET(DPM_TESTBENCH ${DPM_TESTS}/testbench) +SET(DPM_UNIT_TEST ${DPM_TESTS}/unit) +SET(DPM_API_TEST ${DPM_TESTS}/api) -INCLUDE("${TIZEN_PROFILE_NAME}.cmake") - -ADD_EXECUTABLE(${API_TEST_TARGET} ${API_TEST_SOURCES}) - -INCLUDE_DIRECTORIES(SYSTEM ${DPM_LIBS} ${DPM_TESTS}) - -TARGET_LINK_LIBRARIES(${API_TEST_TARGET} dpm glib-2.0) - -INSTALL(TARGETS ${API_TEST_TARGET} DESTINATION bin) +ADD_SUBDIRECTORY(${DPM_UNIT_TEST}) +ADD_SUBDIRECTORY(${DPM_API_TEST}) diff --git a/tests/api/CMakeLists.txt b/tests/api/CMakeLists.txt new file mode 100644 index 0000000..8511ba4 --- /dev/null +++ b/tests/api/CMakeLists.txt @@ -0,0 +1,38 @@ +# +# Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +# +# 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. +# +SET(API_TEST_TARGET "dpm-api-tests") + +SET(API_TEST_SOURCES main.c + testbench.c + admin.c + application.c + context.c + bluetooth.c + manager.c + restriction.c + security.c + wifi.c +) + +INCLUDE("${TIZEN_PROFILE_NAME}.cmake") + +ADD_EXECUTABLE(${API_TEST_TARGET} ${API_TEST_SOURCES}) + +INCLUDE_DIRECTORIES(SYSTEM ${DPM_LIBS} ${DPM_TESTS}) + +TARGET_LINK_LIBRARIES(${API_TEST_TARGET} dpm) + +INSTALL(TARGETS ${API_TEST_TARGET} DESTINATION bin) diff --git a/tests/admin.c b/tests/api/admin.c similarity index 100% rename from tests/admin.c rename to tests/api/admin.c diff --git a/tests/application.c b/tests/api/application.c similarity index 100% rename from tests/application.c rename to tests/api/application.c diff --git a/tests/bluetooth.c b/tests/api/bluetooth.c similarity index 100% rename from tests/bluetooth.c rename to tests/api/bluetooth.c diff --git a/tests/common.cmake b/tests/api/common.cmake similarity index 100% rename from tests/common.cmake rename to tests/api/common.cmake diff --git a/tests/context.c b/tests/api/context.c similarity index 100% rename from tests/context.c rename to tests/api/context.c diff --git a/tests/ivi.cmake b/tests/api/ivi.cmake similarity index 100% rename from tests/ivi.cmake rename to tests/api/ivi.cmake diff --git a/tests/main.c b/tests/api/main.c similarity index 100% rename from tests/main.c rename to tests/api/main.c diff --git a/tests/manager.c b/tests/api/manager.c similarity index 100% rename from tests/manager.c rename to tests/api/manager.c diff --git a/tests/mobile.cmake b/tests/api/mobile.cmake similarity index 100% rename from tests/mobile.cmake rename to tests/api/mobile.cmake diff --git a/tests/password.c b/tests/api/password.c similarity index 100% rename from tests/password.c rename to tests/api/password.c diff --git a/tests/restriction.c b/tests/api/restriction.c similarity index 100% rename from tests/restriction.c rename to tests/api/restriction.c diff --git a/tests/security.c b/tests/api/security.c similarity index 100% rename from tests/security.c rename to tests/api/security.c diff --git a/tests/testbench.c b/tests/api/testbench.c similarity index 100% rename from tests/testbench.c rename to tests/api/testbench.c diff --git a/tests/testbench.h b/tests/api/testbench.h similarity index 100% rename from tests/testbench.h rename to tests/api/testbench.h diff --git a/tests/tv.cmake b/tests/api/tv.cmake similarity index 100% rename from tests/tv.cmake rename to tests/api/tv.cmake diff --git a/tests/wearable.cmake b/tests/api/wearable.cmake similarity index 100% rename from tests/wearable.cmake rename to tests/api/wearable.cmake diff --git a/tests/wifi.c b/tests/api/wifi.c similarity index 100% rename from tests/wifi.c rename to tests/api/wifi.c diff --git a/tests/zone.c b/tests/api/zone.c similarity index 100% rename from tests/zone.c rename to tests/api/zone.c diff --git a/tests/testbench/testbench.cpp b/tests/testbench/testbench.cpp new file mode 100644 index 0000000..bbd0df2 --- /dev/null +++ b/tests/testbench/testbench.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include + +#include "testbench.h" + +namespace testbench { + +Source::Source(const std::string& file, long line, const std::string& msg) : + fileName(file), lineNumber(line), message(msg) +{ +} + +TestResult::TestResult() : + __failureCount(0) +{ +} + +TestResult::~TestResult() +{ +} + +void TestResult::testsStarted() +{ +} + +void TestResult::addFailure(const std::string& name, const Source& source) +{ + std::cout << "Testcase \"" << name << "\"" + << " failed: \"" << source.message << "\"" + << " line " << source.lineNumber + << " in " << source.fileName << std::endl; + + __failureCount++; +} + +void TestResult::testsEnded() +{ + if (__failureCount > 0) { + std::cout << "\nThere were " << __failureCount << " failures" << std::endl; + } else { + std::cout << "\nThere were no test failures" << std::endl; + } +} + +TestSuite::TestSuite(const std::string& name) + : __testName(name) +{ + Testbench::addTestSuite(this); +} + +TestSuite::~TestSuite() +{ +} + +void TestSuite::setup() +{ +} + +void TestSuite::teardown() +{ +} + +void TestSuite::run() +{ + setup(); + + TestCaseRegistry::iterator iter = __registry.begin(); + while (iter != __registry.end()) { + TestSuite::TestCase& testcase = (*iter); + + std::cout << "Entering testcase: " + << testcase.testName << std::endl; + try { + (this->*testcase.function)(); + } catch (...) { + TEST_FAIL("Caught exception from " + + testcase.testName + " testcase"); + } + std::cout << "Leaving testcase: " + << testcase.testName << std::endl; + + iter++; + } + + teardown(); +} + +void TestSuite::registerTestCase(TestFunction func, const std::string& name) +{ + __registry.push_back(TestCase(func, name)); +} + +bool TestSuite::check(long expected, long actual, const std::string& file, long line) +{ + if (expected == actual) { + return true; + } + + std::stringstream stream; + stream << "expected " << expected << " but it was " << actual; + Testbench::report(__testName, Source(file, line, stream.str())); + + return false; +} + +std::unique_ptr Testbench::collector(new TestResult()); + +void Testbench::addTestSuite(TestSuite *testSuite) +{ + instance().add(testSuite); +} + +void Testbench::runAllTestSuites() +{ + instance().run(); +} + +Testbench& Testbench::instance() +{ + static Testbench testbench; + return testbench; +} + +void Testbench::add(TestSuite *testSuite) +{ + __testSuites.push_back(testSuite); +} + +void Testbench::report(const std::string& name, const Source& source) +{ + collector->addFailure(name, source); +} + +void Testbench::run() +{ + collector->testsStarted(); + + TestSuiteRegistry::iterator iter = __testSuites.begin(); + while (iter != __testSuites.end()) { + try { + (*iter)->run(); + } catch (...) { + // Logging exception + } + iter++; + } + + collector->testsEnded(); +} + +} //namespace testbench diff --git a/tests/testbench/testbench.h b/tests/testbench/testbench.h new file mode 100644 index 0000000..1fd6841 --- /dev/null +++ b/tests/testbench/testbench.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __DPM_TESTBENCH_H__ +#define __DPM_TESTBENCH_H__ + +#include + +#include +#include +#include +#include + +namespace testbench { + +struct Source { + Source(const std::string& file, long line, const std::string& msg); + + std::string fileName; + long lineNumber; + std::string message; +}; + +class TestResult { +public: + TestResult(); + virtual ~TestResult(); + virtual void testsStarted(); + virtual void addFailure(const std::string& name, const Source& source); + virtual void testsEnded(); + +private: + int __failureCount; +}; + +class TestSuite { +public: + TestSuite(const std::string& name); + virtual ~TestSuite(); + + TestSuite(const TestSuite&) = delete; + TestSuite& operator=(const TestSuite&) = delete; + + void run(); + + const std::string& name() const { + return __testName; + } + +protected: + typedef void (TestSuite::*TestFunction)(); + + struct TestCase { + TestCase(TestFunction func, const std::string& name) : + function(func), testName(name) + { + } + + TestFunction function; + std::string testName; + }; + + virtual void setup(); + virtual void teardown(); + +#define addTest(func) \ + registerTestCase(static_cast(&func), #func) + +#define addTestWithName(func, name) \ + registerTestCase(static_cast(&func), name) + + void registerTestCase(TestFunction func, const std::string& name); + bool check(long expected, long actual, const std::string& file, long line); + +protected: + std::string __testName; + +private: + typedef std::vector TestCaseRegistry; + + TestCaseRegistry __registry; +}; + +class Testbench { +public: + static void addTestSuite(TestSuite *testSuite); + static void runAllTestSuites(); + static void report(const std::string& name, const Source& source); + +private: + static Testbench& instance(); + + void add(TestSuite *testSuite); + void run(); + +private: + static std::unique_ptr collector; + + typedef std::vector TestSuiteRegistry; + TestSuiteRegistry __testSuites; +}; + +#ifndef __FILENAME__ +#define __FILENAME__ \ +(::strrchr(__FILE__, '/') ? ::strrchr(__FILE__, '/') + 1 : __FILE__) +#endif + +#define TESTCASE(TestName) \ +class TestName##TestCase : public testbench::TestSuite {\ +public: \ + TestName##TestCase() \ + : TestSuite(#TestName) \ + { \ + addTestWithName(TestName##TestCase::standalone, #TestName); \ + } \ + void standalone(); \ +} TestName##TestCase##Instance; \ +void TestName##TestCase::standalone() + +#define TEST_CHECK(condition) \ +{ \ + if (!(condition)) { \ + testbench::Testbench::report(__testName, \ + testbench::Source(__FILENAME__, __LINE__, #condition)); \ + return; \ + } \ +} + +#define TEST_EXPECT(expected, actual) \ +{ \ + __typeof__(expected) _exp = (expected); \ + __typeof__(actual) _act = (actual); \ + if (_exp != _act) { \ + std::stringstream _stream; \ + _stream << "expected " << _exp \ + << " but it was " << _act; \ + testbench::Testbench::report(__testName, \ + testbench::Source(__FILENAME__, __LINE__, _stream.str())); \ + return; \ + } \ +} + +#define TEST_FAIL(text) \ +{ \ + testbench::Testbench::report(__testName, \ + testbench::Source(__FILENAME__, __LINE__, (text))); \ + return; \ +} +} // namespace testbench +#endif //!__DPM_TESTBENCH_H__ diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt new file mode 100755 index 0000000..0960f61 --- /dev/null +++ b/tests/unit/CMakeLists.txt @@ -0,0 +1,41 @@ +# +# Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +# +# 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. +# +SET(UNIT_TEST_TARGET "dpm-unit-tests") + +SET(UNIT_TEST_SOURCES main.cpp + database.cpp + dbus.cpp + eventfd.cpp + filesystem.cpp + logger.cpp + misc.cpp + proc.cpp + rmi.cpp + shadow.cpp + xml.cpp + ${DPM_TESTBENCH}/testbench.cpp +) + +ADD_EXECUTABLE(${UNIT_TEST_TARGET} ${UNIT_TEST_SOURCES}) + +PKG_CHECK_MODULES(TESTS_DEPS REQUIRED glib-2.0) +INCLUDE_DIRECTORIES(SYSTEM ${TESTS_DEPS_INCLUDE_DIRS} ${DPM_COMMON} ${DPM_LIBS} ${DPM_TESTS}) + +TARGET_LINK_LIBRARIES(${UNIT_TEST_TARGET} dpm-common) + +INSTALL(TARGETS ${UNIT_TEST_TARGET} DESTINATION bin) +INSTALL(FILES data/sample-policy.xml DESTINATION ${DATA_INSTALL_DIR}) +INSTALL(FILES data/unittest-proc.sh DESTINATION ${DATA_INSTALL_DIR}) diff --git a/tests/unit/data/sample-policy.xml b/tests/unit/data/sample-policy.xml new file mode 100755 index 0000000..6768eac --- /dev/null +++ b/tests/unit/data/sample-policy.xml @@ -0,0 +1,147 @@ + + + 0.1.0 + + allowed + allowed + + + + allowed + allowed + allowed + + + + 0 + 0 + 0 + 0 + 0 + empty + 0 + 0 + 0 + 0 + 0 + 0 + 0 + empty + + + + + + allowed + allowed + + + + + + allowed + none + none + disabled + allowed + enabled + disabled + + + + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + disabled + disabled + + + + allowed + allowed + allowed + allowed + allowed + allowed + allowed + + + + disabled + disabled + enabled + + + + 0 + 0 + 0 + 0 + 0 + 0 + 0,0,0 + 0,0,0 + 0,0,0 + 0,0,0 + 0,0,0 + 0 + 0 + + + + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + allowed + + + + allowed + allowed + allowed + allowed + allowed + + + + empty + empty + allowed + allowed + empty + empty + + diff --git a/tests/unit/data/unittest-proc.sh b/tests/unit/data/unittest-proc.sh new file mode 100755 index 0000000..17a7b68 --- /dev/null +++ b/tests/unit/data/unittest-proc.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +while true; +do + sleep 4 +done diff --git a/tests/unit/database.cpp b/tests/unit/database.cpp new file mode 100644 index 0000000..e24b12c --- /dev/null +++ b/tests/unit/database.cpp @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include + +#include +#include +#include + +#include "exception.h" + +#include "db/connection.h" +#include "db/statement.h" +#include "db/column.h" + +#include "testbench/testbench.h" + +const std::string TestbenchDataSource = "/tmp/dpm-testbench.db"; + +TESTCASE(DatabaseTest) +{ + std::string query = "CREATE TABLE IF NOT EXISTS CLIENT(" \ + "ID INTEGER PRIMARY KEY AUTOINCREMENT," \ + "PKG TEXT," \ + "KEY TEXT," \ + "IS_USED INTEGER," \ + "USER INTEGER)"; + + try { + database::Connection db(TestbenchDataSource, database::Connection::ReadWrite | database::Connection::Create); + db.exec(query); + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(InvalidStatementTest) +{ + try { + database::Connection db(TestbenchDataSource, database::Connection::ReadWrite | database::Connection::Create); + database::Statement stmt(db, "INVALID STATEMENT"); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(InvalidStatementTest2) +{ + try { + database::Connection db(TestbenchDataSource, database::Connection::ReadWrite | database::Connection::Create); + db.exec("INVALID"); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(ColumnBindTestWithIndex1) +{ + std::string query = "INSERT INTO CLIENT VALUES (NULL, ?, ?, ?, ?)"; + + try { + const char *str = "PACKAGE"; + void *blob = (void *)str; + double user = 5001; + sqlite3_int64 used = 1; + std::string key = "test key"; + + database::Connection db(TestbenchDataSource, database::Connection::ReadWrite | database::Connection::Create); + database::Statement stmt(db, query); + stmt.bind(1, blob, 8); + stmt.bind(2, key); + stmt.bind(3, used); + stmt.bind(4, user); + stmt.exec(); + database::Statement select(db, "SELECT * FROM CLIENT"); + + TEST_EXPECT(5, select.getColumnCount()); + stmt.clearBindings(); + stmt.reset(); + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(ColumnBindTestWithIndex2) +{ + std::string query = "INSERT INTO CLIENT VALUES (NULL, ?, ?, ?, ?)"; + + try { + database::Connection db(TestbenchDataSource, database::Connection::ReadWrite | database::Connection::Create); + database::Statement stmt(db, query); + stmt.bind(1, "TEST PACKAGE"); + stmt.bind(2, "TEST KEY"); + stmt.bind(3, false); + stmt.bind(4, 5001); + stmt.exec(); + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(ColumnBindTestWithName1) +{ + std::string query = "INSERT INTO CLIENT VALUES (NULL, :PKG, :KEY, :IS_USED, :USER)"; + + try { + database::Connection db(TestbenchDataSource, database::Connection::ReadWrite | database::Connection::Create); + database::Statement stmt(db, query); + stmt.bind(":PKG", "TEST PACKAGE"); + stmt.bind(":KEY", "TEST KEY"); + stmt.bind(":IS_USED", true); + stmt.bind(":USER", 5001); + stmt.exec(); + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(ColumnBindNullTest) +{ + std::string query = "INSERT INTO CLIENT VALUES (NULL, :PKG, :KEY, :IS_USED, :USER)"; + + try { + database::Connection db(TestbenchDataSource, database::Connection::ReadWrite | database::Connection::Create); + database::Statement stmt(db, query); + stmt.bind(":PKG"); + stmt.bind(2); + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(ColumnBindTestWithName2) +{ + std::string query = "INSERT INTO CLIENT VALUES (NULL, :PKG, :KEY, :IS_USED, :USER)"; + + try { + const char *str = "PACKAGE"; + void *blob = (void *)str; + double user = 5001; + sqlite3_int64 used = 1; + std::string key = "test key"; + + database::Connection db(TestbenchDataSource, database::Connection::ReadWrite | database::Connection::Create); + database::Statement stmt(db, query); + stmt.bind(":PKG", blob, 8); + stmt.bind(":KEY", key); + stmt.bind(":IS_USED", used); + stmt.bind(":USER", user); + stmt.exec(); + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(ColumnTest) +{ + try { + database::Connection db(TestbenchDataSource, database::Connection::ReadWrite | database::Connection::Create); + database::Statement select(db, "SELECT * FROM CLIENT"); + while (select.step()) { + for (int i = 0; i < select.getColumnCount(); i++) { + if (select.isNullColumn(i)) { + continue; + } + select.getColumnName(i); + } + std::cout << std::endl; + + database::Column id = select.getColumn(0); + database::Column pkg = select.getColumn(1); + database::Column key = select.getColumn(2); + database::Column used = select.getColumn(3); + + id.getName(); id.getInt(); id.getInt64(); id.getDouble(); id.getType(); id.getBytes(); id.getDouble(); + pkg.getName(); pkg.getText(); pkg.getType(); pkg.getBytes(); pkg.getBlob(); + key.getName(); key.getText(); key.getType(); key.getBytes(); key.getBlob(); + used.getName(); used.getInt(); used.getInt64(); used.getDouble(); used.getType(); used.getBytes(); + } + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(ColumnOutRange1) +{ + try { + database::Connection db(TestbenchDataSource, database::Connection::ReadWrite | database::Connection::Create); + database::Statement select(db, "SELECT * FROM CLIENT"); + select.step(); + database::Column column = select.getColumn(32); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(ColumnOutRange2) +{ + try { + database::Connection db(TestbenchDataSource, database::Connection::ReadWrite | database::Connection::Create); + database::Statement select(db, "SELECT * FROM CLIENT"); + select.step(); + select.isNullColumn(32); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(ColumnOutRange3) +{ + try { + database::Connection db(TestbenchDataSource, database::Connection::ReadWrite | database::Connection::Create); + database::Statement select(db, "SELECT * FROM CLIENT"); + select.step(); + select.getColumnName(32); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(ColumnBindOutRange1) +{ + std::string query = "INSERT INTO CLIENT VALUES (NULL, :PKG, :KEY, :IS_USED, :USER)"; + + try { + database::Connection db(TestbenchDataSource, database::Connection::ReadWrite | database::Connection::Create); + database::Statement stmt(db, query); + try { + stmt.bind(":TPK", "TEST PACKAGE"); + } catch (runtime::Exception& e) { + } + + try { + stmt.bind(":TPK", (int)10); + } catch (runtime::Exception& e) { + } + + try { + stmt.bind(":TPK", (sqlite3_int64)10); + } catch (runtime::Exception& e) { + } + + try { + stmt.bind(":TPK", (double)10); + } catch (runtime::Exception& e) { + } + + try { + stmt.bind(":TPK", "invalid"); + } catch (runtime::Exception& e) { + } + + try { + stmt.bind(":TPK", std::string("invalid")); + } catch (runtime::Exception& e) { + } + + try { + stmt.bind(":TPK", (void *)NULL, 12); + } catch (runtime::Exception& e) { + } + + try { + stmt.bind(":TPK"); + } catch (runtime::Exception& e) { + } + + stmt.exec(); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(ColumnBindOutRange2) +{ + std::string query = "INSERT INTO CLIENT VALUES (NULL, :PKG, :KEY, :IS_USED, :USER)"; + + try { + database::Connection db(TestbenchDataSource, database::Connection::ReadWrite | database::Connection::Create); + database::Statement stmt(db, query); + try { + stmt.bind(32, "TEST PACKAGE"); + } catch (runtime::Exception& e) { + } + + try { + stmt.bind(32, (int)10); + } catch (runtime::Exception& e) { + } + + try { + stmt.bind(32, (sqlite3_int64)10); + } catch (runtime::Exception& e) { + } + + try { + stmt.bind(32, (double)10); + } catch (runtime::Exception& e) { + } + + try { + stmt.bind(32, "invalid"); + } catch (runtime::Exception& e) { + } + + try { + stmt.bind(32, std::string("invalid")); + } catch (runtime::Exception& e) { + } + + try { + stmt.bind(32, (void *)NULL, 12); + } catch (runtime::Exception& e) { + } + + try { + stmt.bind(32); + } catch (runtime::Exception& e) { + } + + stmt.exec(); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(InvalidDB) +{ + try { + database::Connection db("/tmp/invalid.db", database::Connection::ReadWrite); + } catch (runtime::Exception& e) { + } +} diff --git a/tests/unit/dbus.cpp b/tests/unit/dbus.cpp new file mode 100644 index 0000000..d1e5695 --- /dev/null +++ b/tests/unit/dbus.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "exception.h" +#include "dbus/connection.h" +#include "dbus/variant.h" +#include "audit/logger.h" + +#include "testbench/testbench.h" + +TESTCASE(DbusNegativeTest) +{ + try { + dbus::Connection &systemDBus = dbus::Connection::getSystem(); + systemDBus.methodcall("Unknown", "Unknown", "Unknown", "Unknown", -1, "", ""); + } catch (std::exception& e) { + } +} diff --git a/tests/unit/eventfd.cpp b/tests/unit/eventfd.cpp new file mode 100644 index 0000000..3e7c376 --- /dev/null +++ b/tests/unit/eventfd.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include + +#include "eventfd.h" +#include "error.h" +#include "exception.h" +#include "audit/logger.h" + +#include "testbench/testbench.h" + +TESTCASE(EventFdHandleNegative) +{ + try { + runtime::EventFD evtfd(0, -1); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(EventFdSendPositive) +{ + try { + runtime::EventFD evtfd; + evtfd.send(); + evtfd.receive(); + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(EventFdSendNegative) +{ + try { + runtime::EventFD evtfd; + evtfd.close(); + evtfd.send(); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(EventFdReceiveNegative) +{ + try { + runtime::EventFD evtfd; + evtfd.close(); + evtfd.receive(); + } catch (runtime::Exception& e) { + } +} + + diff --git a/tests/unit/filesystem.cpp b/tests/unit/filesystem.cpp new file mode 100644 index 0000000..4047a55 --- /dev/null +++ b/tests/unit/filesystem.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "exception.h" +#include "filesystem.h" + +#include "testbench/testbench.h" + +TESTCASE(DirectoryIteration) +{ + runtime::DirectoryIterator iter("/dev"); + runtime::DirectoryIterator end; + + TEST_EXPECT(false, iter == end); + + while (iter != end) { + ++iter; + } +} + +TESTCASE(FileIO) +{ + char testbuf[100] = "Test Data"; + runtime::File tmp("/tmp/test-file"); + try { + tmp.create(755); + tmp.lock(); + tmp.write(testbuf, ::strlen(testbuf)); + tmp.unlock(); + tmp.close(); + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } + + char readbuf[100]; + try { + runtime::File tmpFile("/tmp/test-file", O_RDWR); + tmpFile.read(readbuf, ::strlen(testbuf)); + tmpFile.close(); + tmpFile.remove(); + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(DirOperation) +{ + runtime::File testDir("/tmp/dpm-unit-test/dir"); + try { + testDir.makeDirectory(true, ::getuid(), ::getgid()); + testDir.chown(::getuid(), ::getgid(), false); + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } + + runtime::File dir("/tmp/dpm-unit-test"); + try { + dir.chmod(777, true); + dir.remove(true); + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(FileAttribute) +{ + runtime::File tmp("/tmp"); + + TEST_EXPECT(true, tmp.exists()); + TEST_EXPECT(true, tmp.canRead()); + TEST_EXPECT(true, tmp.canWrite()); + TEST_EXPECT(true, tmp.canExecute()); + TEST_EXPECT(false, tmp.isLink()); + TEST_EXPECT(false, tmp.isFile()); + TEST_EXPECT(true, tmp.isDirectory()); + TEST_EXPECT(false, tmp.isDevice()); + + std::cout << " UID: " << tmp.getUid() + << " GID: " << tmp.getGid() + << " Size: " << tmp.size() + << " Mode: " << tmp.getMode() + << " Path: " << tmp.getPath() + << " File: " << tmp.getName() << std::endl; +} + +TESTCASE(FileAttributeNegative) +{ + try { + runtime::File tmp("/unknown"); + + TEST_EXPECT(false, tmp.exists()); + TEST_EXPECT(false, tmp.canRead()); + TEST_EXPECT(false, tmp.canWrite()); + TEST_EXPECT(false, tmp.canExecute()); + + try { + tmp.isLink(); + } catch (runtime::Exception& e) { + } + + try { + tmp.isFile(); + } catch (runtime::Exception& e) { + } + + try { + tmp.isDirectory(); + } catch (runtime::Exception& e) { + } + + try { + tmp.isDevice(); + } catch (runtime::Exception& e) { + } + } catch (runtime::Exception& e) { + } +} + +TESTCASE(FileDevice) +{ + runtime::File tmp("/dev/kmem"); + + TEST_EXPECT(true, tmp.isDevice()); +} + +TESTCASE(FileSymlinkTest) +{ + runtime::File tmp("/var"); + + TEST_EXPECT(true, tmp.isLink()); +} + +TESTCASE(FileReferenceTest) +{ + runtime::File one("/tmp"); + runtime::File two(one); +} diff --git a/tests/unit/logger.cpp b/tests/unit/logger.cpp new file mode 100644 index 0000000..a0e1809 --- /dev/null +++ b/tests/unit/logger.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include + +#include "array.h" +#include "error.h" +#include "exception.h" +#include "audit/logger.h" + +#include "testbench/testbench.h" + +TESTCASE(LogMacroTest) +{ + TRACE("Trace"); + INFO("Info"); + DEBUG("Debug"); + WARN("Warning"); + ERROR("Error"); +} + +TESTCASE(LogSeverityTest) +{ + try { + audit::LogLevelToString((audit::LogLevel)-1); + } catch (runtime::Exception& e) { + } +} diff --git a/tests/unit/main.cpp b/tests/unit/main.cpp new file mode 100644 index 0000000..c053fc0 --- /dev/null +++ b/tests/unit/main.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "testbench/testbench.h" +#include "audit/logger.h" + +int main(int /*argc*/, char** /*argv*/) +{ + audit::Logger::setLogLevel(audit::LogLevel::Trace); + testbench::Testbench::runAllTestSuites(); + + return 0; +} diff --git a/tests/unit/misc.cpp b/tests/unit/misc.cpp new file mode 100644 index 0000000..b8f2c82 --- /dev/null +++ b/tests/unit/misc.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include + +#include "array.h" +#include "error.h" +#include "exception.h" +#include "audit/logger.h" + +#include "testbench/testbench.h" + +TESTCASE(ErrorMessage) +{ + std::cout << "Error Message: " << runtime::GetSystemErrorMessage(EINTR) << std::endl; +} + +TESTCASE(Array) +{ + std::vector vec = { + "abc", + "def" + }; + + runtime::Array array(std::move(vec)); + while (array.isEnd() == false) { + std::string* str = array.next(); + TEST_EXPECT(true, str != nullptr); + } +} + +TESTCASE(ArrayCopy) +{ + std::vector vec = { + "abc", + "def" + }; + + runtime::Array array(vec); + while (array.isEnd() == false) { + std::string* str = array.next(); + TEST_EXPECT(true, str != nullptr); + } +} + diff --git a/tests/unit/proc.cpp b/tests/unit/proc.cpp new file mode 100644 index 0000000..505de01 --- /dev/null +++ b/tests/unit/proc.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include + +#include "exception.h" +#include "process.h" +#include "audit/logger.h" + +#include "testbench/testbench.h" + +TESTCASE(ProcWithArg) +{ + try { + std::vector args = { + "-l", + "-a" + }; + runtime::Process proc("/bin/ls > /dev/null", args); + TEST_EXPECT(true, proc.execute() != -1); + proc.waitForFinished(); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(ProcKill) +{ + try { + runtime::Process proc("/opt/data/unittest-proc.sh"); + TEST_EXPECT(true, proc.execute() != -1); + if (proc.isRunning()) { + proc.kill(); + proc.waitForFinished(); + } + } catch (runtime::Exception& e) { + } +} + +TESTCASE(ProcTerminate) +{ + try { + runtime::Process proc("/opt/data/unittest-proc.sh"); + TEST_EXPECT(true, proc.execute() != -1); + if (proc.isRunning()) { + proc.terminate(); + proc.waitForFinished(); + } + } catch (runtime::Exception& e) { + } +} + +TESTCASE(ProcInvalidProcess) +{ + try { + runtime::Process proc("/opt/data/unittest-proc.sh"); + TEST_EXPECT(true, proc.execute() != -1); + proc.terminate(); + proc.waitForFinished(); + TEST_EXPECT(false, proc.isRunning()); + try { + proc.kill(); + } catch (runtime::Exception& e) { + } + + try { + proc.terminate(); + } catch (runtime::Exception& e) { + } + + try { + proc.waitForFinished(); + } catch (runtime::Exception& e) { + } + } catch (runtime::Exception& e) { + } +} diff --git a/tests/unit/rmi.cpp b/tests/unit/rmi.cpp new file mode 100644 index 0000000..ffcff81 --- /dev/null +++ b/tests/unit/rmi.cpp @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "data-type.h" +#include "file-descriptor.h" +#include "rmi/service.h" +#include "rmi/client.h" +#include "audit/logger.h" + +#include "testbench/testbench.h" + +const std::string IPC_TEST_ADDRESS = "/tmp/.dpm-test"; + +class TestServer { +public: + TestServer() + { + service.reset(new rmi::Service(IPC_TEST_ADDRESS)); + + service->registerMethod(this, "", (String)(TestServer::method1)(String)); + service->registerMethod(this, "", (String)(TestServer::method2)(String, String)); + service->registerMethod(this, "", (String)(TestServer::method3)(String, String, String)); + service->registerMethod(this, "", (String)(TestServer::method4)(String, String, String, String)); + + service->registerMethod(this, "", (FileDescriptor)(TestServer::signalProvider)(std::string)); + service->registerMethod(this, "", (FileDescriptor)(TestServer::policyNotificationProvider)(std::string)); + + service->registerNonparametricMethod(this, "", (int)(TestServer::sendSignal)()); + service->registerNonparametricMethod(this, "", (int)(TestServer::sendPolicyChangeNotification)()); + + service->createNotification("TestPolicyChanged"); + service->createNotification("TestSignal"); + } + + void run() + { + service->start(); + } + + String method1(String& arg1) + { + return String("Method1 result"); + } + + String method2(String& arg1, String& arg2) + { + return String("Method2 result"); + } + + String method3(String& arg1, String& arg2, String& arg3) + { + return String("Method3 result"); + } + + String method4(String& arg1, String& arg2, String& arg3, String& arg4) + { + return String("Method4 result"); + } + + int sendPolicyChangeNotification() + { + service->notify("TestPolicyChanged", 1234); + return 0; + } + + int sendSignal() + { + service->notify("TestSignal"); + return 0; + } + + FileDescriptor signalProvider(const std::string& name) + { + return service->subscribeNotification(name); + } + + FileDescriptor policyNotificationProvider(const std::string& name) + { + return service->subscribeNotification(name); + } + +private: + std::unique_ptr service; +}; + +class TestClient { +public: + TestClient() : + signalTriggered(false), + policyChangeNotificationTriggered(false) + { + } + + void connect() + { + auto policyChangedListener = [this](const std::string& name, int value) { + policyChangeNotificationTriggered = true; + }; + + auto policySignalListener = [this](const std::string& name) { + signalTriggered = true; + }; + + client.reset(new rmi::Client(IPC_TEST_ADDRESS)); + client->connect(); + + client->subscribe("TestServer::policyNotificationProvider", + "TestPolicyChanged", policyChangedListener); + client->subscribe("TestServer::signalProvider", + "TestSignal", policySignalListener); + } + + void disconnect() + { + client.reset(); + } + + String method1(String& arg1) + { + return client->methodCall("TestServer::method1", arg1); + } + + String method2(String& arg1, String& arg2) + { + return client->methodCall("TestServer::method2", arg1, arg2); + } + + String method3(String& arg1, String& arg2, String& arg3) + { + return client->methodCall("TestServer::method3", arg1, arg2, arg3); + } + + String method4(String& arg1, String& arg2, String& arg3, String& arg4) + { + return client->methodCall("TestServer::method4", arg1, arg2, arg3, arg4); + } + + void requestSignal() + { + signalTriggered = false; + client->methodCall("TestServer::sendSignal"); + while (!signalTriggered) { + ::sleep(1); + } + } + + void requestPolicyChangeNotification() + { + policyChangeNotificationTriggered = false; + client->methodCall("TestServer::sendPolicyChangeNotification"); + while (!policyChangeNotificationTriggered) { + sleep(1); + } + } + + String invalidMethod(String& arg) + { + return client->methodCall("TestServer::invalidMethod", arg); + } + +private: + volatile bool signalTriggered; + volatile bool policyChangeNotificationTriggered; + std::unique_ptr client; +}; + +int WaitForFile(const std::string& path, const unsigned int timeout) +{ + struct stat st; + unsigned int loop = 0; + + while (stat(path.c_str(), &st) == -1) { + if (errno != ENOENT) { + ERROR("Error on waitting for: " + path); + return -1; + } + + if (((++loop) * 100) > timeout) { + ERROR("Error on waitting for: " + path); + return -1; + } + + usleep(100 * 1000); + } + + return 0; +} + +int WaitForPid(pid_t pid) +{ + int status, ret; + char errmsg[256]; + + do { + ret = waitpid(pid, &status, 0); + if (ret == -1) { + if (errno != EINTR) { + ERROR("Wait Pid failed: " + std::to_string(pid) + "(" + strerror_r(errno, errmsg, sizeof(errmsg)) + ")"); + return -1; + } + } + } while (ret == EINTR || ret != pid); + + return status; +} + +pid_t PrepareTestServer(void) +{ + ::unlink(IPC_TEST_ADDRESS.c_str()); + + pid_t pid = fork(); + + if (pid < 0) { + return -1; + } + + if (pid == 0) { + try { + TestServer server; + server.run(); + } catch (std::exception& e) { + ERROR(e.what()); + return -1; + } + + return 0; + } + + return pid; +} + +class IpcTestSuite : public testbench::TestSuite { +public: + IpcTestSuite(const std::string& name) : + testbench::TestSuite(name) + { + addTest(IpcTestSuite::connectionTest); + addTest(IpcTestSuite::remoteMethodCallTest); + addTest(IpcTestSuite::notificationTest); + } + + void setup() + { + pid = PrepareTestServer(); + if (pid == -1) { + ERROR("Preparing test server failed"); + return; + } + + WaitForFile(IPC_TEST_ADDRESS, 1000); + } + + void teardown() + { + if (::kill(pid, SIGTERM) == -1) { + return; + } + + int status = WaitForPid(pid); + if (status == -1 || !WIFEXITED(status)) { + return; + } + } + + void connectionTest() + { + try { + TestClient client; + client.connect(); + client.disconnect(); + } catch (runtime::Exception& e) { + ERROR(e.what()); + } + } + + void notificationTest() + { + try { + TestClient client; + client.connect(); + + client.requestSignal(); + client.requestPolicyChangeNotification(); + + client.disconnect(); + } catch (runtime::Exception& e) { + ERROR(e.what()); + } + } + + void remoteMethodCallTest() + { + try { + TestClient client; + client.connect(); + + String param1("First Parameter"); + String param2("Second Parameter"); + String param3("Third Parameter"); + String param4("Fourth Parameter"); + + String result1 = client.method1(param1); + String result2 = client.method2(param1, param2); + String result3 = client.method3(param1, param2, param3); + String result4 = client.method4(param1, param2, param3, param4); + + client.requestSignal(); + client.requestPolicyChangeNotification(); + + client.disconnect(); + } catch (runtime::Exception& e) { + ERROR(e.what()); + } + } + +private: + pid_t pid; +}; + +IpcTestSuite ipcTestSuite("IpcTestSuite"); diff --git a/tests/unit/shadow.cpp b/tests/unit/shadow.cpp new file mode 100644 index 0000000..52a1d3d --- /dev/null +++ b/tests/unit/shadow.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include + +#include "auth/user.h" +#include "auth/group.h" + +#include "exception.h" +#include "auth/user.h" +#include "auth/group.h" +#include "testbench/testbench.h" + +TESTCASE(GetGroupTest) +{ + try { + runtime::Group group("users"); + runtime::Group another(group); + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(GetUserTest) +{ + try { + runtime::User user("root"); + runtime::User another(user); + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(GetGroupNegativeTest) +{ + try { + runtime::Group group("invalid"); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(GetGroupNegativeTest2) +{ + try { + runtime::Group group(-1); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(GetUserNegativetest) +{ + try { + runtime::User user("invalid"); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(GetUserNegativetest2) +{ + try { + runtime::User user(-1); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(GetCurrentGroupTest) +{ + try { + runtime::Group group; + runtime::Group another(group.getGid()); + } catch (runtime::Exception& e) { + } +} + +TESTCASE(GetCurrentUserTest) +{ + try { + runtime::User user; + runtime::User another(user.getUid()); + } catch (runtime::Exception& e) { + } +} diff --git a/tests/unit/xml.cpp b/tests/unit/xml.cpp new file mode 100644 index 0000000..56f80dc --- /dev/null +++ b/tests/unit/xml.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include + +#include +#include +#include + +#include "exception.h" + +#include "xml/parser.h" +#include "xml/document.h" +#include "audit/logger.h" + +#include "testbench/testbench.h" + +const std::string testXmlFilePath = "/opt/data/dpm/sample-policy.xml"; + +TESTCASE(XPath) +{ + try { + xml::Document* document = xml::Parser::parseFile(testXmlFilePath); + xml::Node::NodeList nodes = document->evaluate("//policy-group[@name='APPLICATION']/policy[@name='SET_APP_INSTALLATION_MODE']"); + xml::Node::NodeList::iterator iter = nodes.begin(); + + TEST_EXPECT(false, iter == nodes.end()); + + while (iter != nodes.end()) { + ++iter; + } + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(XmlDomTree) +{ + try { + xml::Document* document = xml::Parser::parseFile(testXmlFilePath); + + xml::Node& root = document->getRootNode(); + + xml::Node::NodeList list = root.getChildren(); + xml::Node::NodeList::iterator iter = list.begin(); + + TEST_EXPECT(false, iter == list.end()); + + while (iter != list.end()) { + ++iter; + } + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(XmlGenerate) +{ + try { + xml::Document doc("TestNode", "0.1"); + xml::Node &root = doc.getRootNode(); + xml::Node node = root.addNewChild("ChildNode"); + TEST_EXPECT("ChildNode", node.getName()); + + node.setName("ModifiedChildNode"); + TEST_EXPECT("ModifiedChildNode", node.getName()); + + node.setContent("Content"); + TEST_EXPECT("Content", node.getContent()); + + node.setProp("Prop", "Value"); + TEST_EXPECT("Value", node.getProp("Prop")); + + doc.write("/tmp/test.xml", "UTF-8", true); + } catch (runtime::Exception& e) { + TEST_FAIL(e.what()); + } +} + +TESTCASE(XmlException) +{ + try { + xml::Parser::parseFile("Invalid Source"); + } catch (runtime::Exception& e) { + } +} diff --git a/tools/syspopup/CMakeLists.txt b/tools/syspopup/CMakeLists.txt index b407ac1..1b92cfb 100644 --- a/tools/syspopup/CMakeLists.txt +++ b/tools/syspopup/CMakeLists.txt @@ -5,8 +5,8 @@ INCLUDE_DIRECTORIES(./include) FIND_PACKAGE(PkgConfig REQUIRED) PKG_CHECK_MODULES(dpm_syspopup_pkgs REQUIRED - dlog - glib-2.0 + dlog + glib-2.0 bundle efl-extension elementary diff --git a/zone/cli/CMakeLists.txt b/zone/cli/CMakeLists.txt index a76e356..44a6cb1 100644 --- a/zone/cli/CMakeLists.txt +++ b/zone/cli/CMakeLists.txt @@ -30,15 +30,13 @@ SET_TARGET_PROPERTIES(${ZONE_CLI_NAME} PROPERTIES PREFIX "" LINK_FLAGS "-pie" ) -PKG_CHECK_MODULES(ZONE_CLI_DEPS REQUIRED - klay - glib-2.0 - libxml-2.0 - capi-appfw-package-manager - capi-appfw-app-manager +PKG_CHECK_MODULES(ZONE_CLI_DEPS REQUIRED + glib-2.0 + capi-appfw-package-manager + capi-appfw-app-manager ) -INCLUDE_DIRECTORIES(SYSTEM ${ZONE_CLI_DEPS_INCLUDE_DIRS} ${ZONE_MODULE} ${ZONE_LIBS}) -TARGET_LINK_LIBRARIES(${ZONE_CLI_NAME} ${ZONE_CLI_DEPS_LIBRARIES} zone) +INCLUDE_DIRECTORIES(SYSTEM ${ZONE_CLI_DEPS_INCLUDE_DIRS} ${DPM_COMMON} ${ZONE_MODULE} ${ZONE_LIBS}) +TARGET_LINK_LIBRARIES(${ZONE_CLI_NAME} ${ZONE_CLI_DEPS_LIBRARIES} dpm-common zone) INSTALL(TARGETS ${ZONE_CLI_NAME} DESTINATION sbin) diff --git a/zone/cli/zone-admin-cli.cpp b/zone/cli/zone-admin-cli.cpp index f5fb71b..65a502c 100644 --- a/zone/cli/zone-admin-cli.cpp +++ b/zone/cli/zone-admin-cli.cpp @@ -24,31 +24,33 @@ */ #define _XOPEN_SOURCE -#include #include -#include -#include -#include #include #include #include #include -#include -#include -#include - -#include -#include +#include +#include +#include +#include +#include -#include #include #include -#include #include +#include + +#include +#include #include "session.h" +#include "error.h" +#include "exception.h" +#include "filesystem.h" +#include "auth/user.h" + #define DEFAULT_SHELL "/bin/bash" diff --git a/zone/libs/CMakeLists.txt b/zone/libs/CMakeLists.txt index 85f5d7e..6575ea5 100755 --- a/zone/libs/CMakeLists.txt +++ b/zone/libs/CMakeLists.txt @@ -37,13 +37,12 @@ SET(CAPI_INCLUDE_FILES zone/zone.h SET (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack") -PKG_CHECK_MODULES(ZONE_LIBS_DEPS REQUIRED - klay - glib-2.0 - capi-appfw-package-manager - capi-appfw-app-manager - capi-appfw-app-control - libtzplatform-config +PKG_CHECK_MODULES(ZONE_LIBS_DEPS REQUIRED + glib-2.0 + capi-appfw-package-manager + capi-appfw-app-manager + capi-appfw-app-control + libtzplatform-config ) ADD_LIBRARY(${PROJECT_NAME} SHARED ${SOURCES}) @@ -51,8 +50,8 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-fvisibility=hid SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${LIB_SOVERSION}) SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${LIB_VERSION}) -INCLUDE_DIRECTORIES(SYSTEM ${ZONE_LIBS_DEPS_INCLUDE_DIRS} ${DPM_POLICY} ${DPM_LIBS} ${ZONE_LIBS}) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${ZONE_LIBS_DEPS_LIBRARIES} pthread) +INCLUDE_DIRECTORIES(SYSTEM ${ZONE_LIBS_DEPS_INCLUDE_DIRS} ${DPM_COMMON} ${DPM_POLICY} ${DPM_LIBS} ${ZONE_LIBS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${ZONE_LIBS_DEPS_LIBRARIES} pthread dpm-common) CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_BINARY_DIR}/${PC_FILE} @ONLY) diff --git a/zone/libs/zone/app-proxy.cpp b/zone/libs/zone/app-proxy.cpp index d3e568f..51275e5 100644 --- a/zone/libs/zone/app-proxy.cpp +++ b/zone/libs/zone/app-proxy.cpp @@ -22,6 +22,8 @@ #include "app-proxy.h" #include "app-info-internal.h" +#include "error.h" +#include "auth/user.h" #include "policy-client.h" #include "zone/app-proxy.hxx" diff --git a/zone/libs/zone/package-proxy.cpp b/zone/libs/zone/package-proxy.cpp index c6fb1fb..8fc20aa 100644 --- a/zone/libs/zone/package-proxy.cpp +++ b/zone/libs/zone/package-proxy.cpp @@ -21,13 +21,14 @@ #include #include #include -#include #include "zone.h" #include "debug.h" #include "package-proxy.h" #include "package-info-internal.h" +#include "error.h" +#include "auth/user.h" #include "policy-client.h" #include "zone/package-proxy.hxx" diff --git a/zone/libs/zone/zone.cpp b/zone/libs/zone/zone.cpp index 420e322..a580bb4 100644 --- a/zone/libs/zone/zone.cpp +++ b/zone/libs/zone/zone.cpp @@ -16,6 +16,7 @@ #include "zone/zone.h" +#include "error.h" #include "debug.h" #include "array.h" diff --git a/zone/module/CMakeLists.txt b/zone/module/CMakeLists.txt index 024ff11..c62674c 100644 --- a/zone/module/CMakeLists.txt +++ b/zone/module/CMakeLists.txt @@ -38,13 +38,8 @@ MARK_AS_ADVANCED(PAM_INCLUDE_DIR PAM_LIBRARY) INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PAM DEFAULT_MSG PAM_LIBRARY PAM_INCLUDE_DIR) -PKG_CHECK_MODULES(ZONE_PAM_DEPS REQUIRED - klay - libxml-2.0 -) - -INCLUDE_DIRECTORIES(${PAM_INCLUDE_DIR} ${ZONE_PAM_DEPS_INCLUDE_DIRS}) -TARGET_LINK_LIBRARIES(${ZONE_PAM_NAME} ${PAM_LIBRARY} ${ZONE_PAM_DEPS_LIBRARIES} pthread) +INCLUDE_DIRECTORIES(${PAM_INCLUDE_DIR} ${DPM_COMMON}) +TARGET_LINK_LIBRARIES(${ZONE_PAM_NAME} ${PAM_LIBRARY} dpm-common pthread) TARGET_COMPILE_DEFINITIONS(${ZONE_PAM_NAME} PRIVATE CONF_PATH="${CONF_INSTALL_DIR}" diff --git a/zone/volume/CMakeLists.txt b/zone/volume/CMakeLists.txt index 171d839..36ffd9a 100644 --- a/zone/volume/CMakeLists.txt +++ b/zone/volume/CMakeLists.txt @@ -21,15 +21,12 @@ SET(ZONE_VOLUME_MANAGER_SOURCES key-manager.cpp main.cpp ) -PKG_CHECK_MODULES(ZONE_VOLUME_MANAGER_DEPS REQUIRED - klay - key-manager -) +PKG_CHECK_MODULES(ZONE_VOLUME_MANAGER_DEPS REQUIRED key-manager) ADD_EXECUTABLE(${ZONE_VOLUME_MANAGER_TARGET} ${ZONE_VOLUME_MANAGER_SOURCES}) -INCLUDE_DIRECTORIES(SYSTEM ${ZONE_VOLUME_MANAGER_DEPS_INCLUDE_DIRS} ${ZONE_LIBS}) +INCLUDE_DIRECTORIES(SYSTEM ${ZONE_VOLUME_MANAGER_DEPS_INCLUDE_DIRS} ${ZONE_LIBS} ${DPM_COMMON}) -TARGET_LINK_LIBRARIES(${ZONE_VOLUME_MANAGER_TARGET} ${ZONE_VOLUME_MANAGER_DEPS_LIBRARIES}) +TARGET_LINK_LIBRARIES(${ZONE_VOLUME_MANAGER_TARGET} ${ZONE_VOLUME_MANAGER_DEPS_LIBRARIES} dpm-common) INSTALL(TARGETS ${ZONE_VOLUME_MANAGER_TARGET} DESTINATION sbin) diff --git a/zone/volume/key-generator.cpp b/zone/volume/key-generator.cpp index d6440f6..334eca6 100755 --- a/zone/volume/key-generator.cpp +++ b/zone/volume/key-generator.cpp @@ -15,23 +15,24 @@ */ +#include +#include #include #include -#include -#include +#include +#include -#include -#include #include #include #include #include -#include -#include - +#include "exception.h" #include "key-generator.h" +#include "error.h" +#include "exception.h" + #define RAND_READ_BYTES 8 #define PBKDF2_ITERATION 1000 #define SHA_BLOCKSIZE 64 diff --git a/zone/volume/key-manager.cpp b/zone/volume/key-manager.cpp index d143c31..78b0d83 100755 --- a/zone/volume/key-manager.cpp +++ b/zone/volume/key-manager.cpp @@ -16,11 +16,11 @@ #include -#include #include #include "key-manager.h" +#include "exception.h" #define addAliasPrefix(alias) \ (ckmcIdSystem + ckmcIdSeperator + alias) diff --git a/zone/volume/main.cpp b/zone/volume/main.cpp index c5ad1ba..0fab661 100755 --- a/zone/volume/main.cpp +++ b/zone/volume/main.cpp @@ -14,27 +14,27 @@ * limitations under the License */ +#include +#include +#include #include #include +#include #include -#include -#include -#include -#include #include #include #include -#include -#include -#include - #include "ecryptfs.h" #include "kernel-keyring.h" #include "key-manager.h" #include "key-generator.h" +#include "error.h" +#include "exception.h" +#include "audit/logger.h" + int generateKey(const std::string& keyName) { if (KeyManager::isKeyExist(keyName)) {