From fdd7fbae926821be7d5229d5cba04396e6f00f99 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 17 Jul 2009 19:00:40 +0200 Subject: =?UTF-8?q?UserBackendHome=20hinzugef=C3=BCgt=20Modul=20zur=20Erst?= =?UTF-8?q?ellung=20von=20Home-Verzeichnissen=20implementert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/UserBackendHome/UserBackendHome.cpp | 195 ++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 src/modules/UserBackendHome/UserBackendHome.cpp (limited to 'src/modules/UserBackendHome/UserBackendHome.cpp') diff --git a/src/modules/UserBackendHome/UserBackendHome.cpp b/src/modules/UserBackendHome/UserBackendHome.cpp new file mode 100644 index 0000000..d524a52 --- /dev/null +++ b/src/modules/UserBackendHome/UserBackendHome.cpp @@ -0,0 +1,195 @@ +/* + * UserBackendHome.cpp + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#include "UserBackendHome.h" +#include +#include + +#include + +#include +#include +#include + +namespace Mad { +namespace Modules { +namespace UserBackendHome { + +bool UserBackendHome::handleConfigEntry(const Core::ConfigEntry &entry, bool handled) { + if(handled) + return false; + + if(entry[0].getKey().matches("UserBackendHome")) { + if(entry[1].getKey().matches("Skeleton")) { + if(entry[2].empty()) + skeleton = entry[1][0]; + } + else if(entry[1].getKey().matches("HomeDir")) { + if(entry[2].empty()) + homeDir = entry[1][0]; + } + else if(!entry[1].empty()) + return false; + + return true; + } + + return false; +} + +void UserBackendHome::setOwnerAndCopyMode(const std::string &source, const std::string &dest, const Common::UserInfo &userInfo, bool isSymlink) { + if((isSymlink ? lchown : chown)(dest.c_str(), (uid_t)userInfo.getUid(), (gid_t)userInfo.getGid()) != 0) { + // TODO Error + } + + struct stat st; + if((isSymlink ? lstat : stat)(source.c_str(), &st) == 0) { + if((isSymlink ? lchmod : chmod)(dest.c_str(), st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != 0) { + // TODO Error + } + } +} + +void migrateOwner(const std::string &path, const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo, bool isSymlink) { + struct stat st; + if((isSymlink ? lstat : stat)(path.c_str(), &st) != 0) { + // TODO Error + return; + } + + uid_t uid = -1; + gid_t gid = -1; + + if(st.st_uid == oldUserInfo.getUid()) + uid = (uid_t)userInfo.getUid(); + + if(st.st_gid == oldUserInfo.getGid()) + gid = (gid_t)userInfo.getGid(); + + if(uid != (uid_t)-1 || gid != (gid_t)-1) { + if((isSymlink ? lchown : chown)(path.c_str(), uid, gid) != 0) { + // TODO Error + } + } +} + +void UserBackendHome::addUser(const Common::UserInfo &userInfo) throw(Core::Exception) { + boost::filesystem::path path(homeDir); + path /= userInfo.getUsername(); + + boost::filesystem::create_directories(path); + + std::string nativePath = path.directory_string(); + if(chown(nativePath.c_str(), (uid_t)userInfo.getUid(), (gid_t)userInfo.getGid()) != 0) { + // TODO Error + } + + boost::filesystem::path skeletonPath(skeleton); + if(!boost::filesystem::is_directory(skeletonPath)) + return; + + boost::filesystem::path oldPath = boost::filesystem::current_path(); + boost::filesystem::current_path(skeletonPath); + + boost::filesystem::recursive_directory_iterator end; + + for(boost::filesystem::recursive_directory_iterator it("."); it != end; ++it) { + boost::filesystem::path source = it->path(); + boost::filesystem::path dest = path / source; + + try { + if(boost::filesystem::is_symlink(it->symlink_status())) { + it.no_push(); + + std::string sourceStr = source.file_string(); + + char link[PATH_MAX]; + int ret = ::readlink(sourceStr.c_str(), link, PATH_MAX); + if(ret <= 0) + continue; + + boost::filesystem::create_symlink(boost::filesystem::path(std::string(link, ret)), dest); + setOwnerAndCopyMode(sourceStr, dest.file_string(), userInfo, true); + } + else if(boost::filesystem::is_directory(it->status())) { + boost::filesystem::create_directory(dest); + setOwnerAndCopyMode(source.directory_string(), dest.directory_string(), userInfo, false); + } + else { + boost::filesystem::copy_file(source, dest); + setOwnerAndCopyMode(source.file_string(), dest.file_string(), userInfo, false); + } + } + catch(...) {} + } + + boost::filesystem::current_path(oldPath); +} + +void UserBackendHome::updateUser(const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo) throw(Core::Exception) { + boost::filesystem::path oldPath(homeDir); + oldPath /= oldUserInfo.getUsername(); + + boost::filesystem::path path(homeDir); + path /= userInfo.getUsername(); + + if(oldPath != path) { + try { + boost::filesystem::rename(oldPath, path); + } + catch(...) { + return; + } + } + + if(oldUserInfo.getUid() == userInfo.getUid() && oldUserInfo.getGid() == userInfo.getGid()) + return; + + std::string nativePath = path.directory_string(); + if(chown(nativePath.c_str(), (uid_t)userInfo.getUid(), (gid_t)userInfo.getGid()) != 0) { + // TODO Error + } + + boost::filesystem::recursive_directory_iterator end; + + for(boost::filesystem::recursive_directory_iterator it(path); it != end; ++it) { + if(boost::filesystem::is_symlink(it->symlink_status())) { + it.no_push(); + + migrateOwner(it->path().file_string(), oldUserInfo, userInfo, true); + } + else if(boost::filesystem::is_directory(it->status())) { + migrateOwner(it->path().directory_string(), oldUserInfo, userInfo, false); + } + else { + migrateOwner(it->path().file_string(), oldUserInfo, userInfo, false); + } + } +} + +void UserBackendHome::deleteUser(const Common::UserInfo &userInfo) throw(Core::Exception) { + boost::filesystem::path path(homeDir); + path /= userInfo.getUsername(); + + boost::filesystem::remove_all(path); +} + +} +} +} -- cgit v1.2.3