Line data Source code
1 : // Copyright (c) 2016-2023 Made to Order Software Corp. All Rights Reserved 2 : // 3 : // https://snapwebsites.org/project/snapdev 4 : // contact@m2osw.com 5 : // 6 : // This program is free software: you can redistribute it and/or modify 7 : // it under the terms of the GNU General Public License as published by 8 : // the Free Software Foundation, either version 3 of the License, or 9 : // (at your option) any later version. 10 : // 11 : // This program is distributed in the hope that it will be useful, 12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 : // GNU General Public License for more details. 15 : // 16 : // You should have received a copy of the GNU General Public License 17 : // along with this program. If not, see <https://www.gnu.org/licenses/>. 18 : #pragma once 19 : 20 : /** \file 21 : * \brief Change the user and group ownership of a file. 22 : * 23 : * This implementation allows for changing the ownership of a file by name. 24 : * The default C system function requires the user identifier and the group 25 : * identifier. Our function accepts strings with the names and automatically 26 : * converts the names in a string. 27 : * 28 : * The chownnm() is defined four times to allow for the user and/or the 29 : * group to be passed either as a string or as an identifier. 30 : */ 31 : 32 : // C++ 33 : // 34 : #include <string> 35 : #include <stdexcept> 36 : 37 : 38 : // C 39 : // 40 : #include <grp.h> 41 : #include <pwd.h> 42 : #include <unistd.h> 43 : 44 : 45 : 46 : namespace snapdev 47 : { 48 : 49 : 50 : constexpr uid_t NO_UID = static_cast<uid_t>(-1); 51 : constexpr uid_t NO_GID = static_cast<gid_t>(-1); 52 : 53 : 54 : /** \brief Convert a user name in its Unix uid_t. 55 : * 56 : * This function searches for a user identifier in /etc/passwd and return 57 : * the corresponding uid_t value. 58 : * 59 : * \param[in] user_name The name of the user to search. 60 : * 61 : * \return The uid_t of the named user or NO_UID. 62 : */ 63 12 : inline uid_t getuid(std::string const & user_name) 64 : { 65 12 : if(!user_name.empty()) 66 : { 67 0 : struct passwd const * pwd(getpwnam(user_name.c_str())); 68 0 : if(pwd != nullptr) 69 : { 70 0 : return pwd->pw_uid; 71 : } 72 : } 73 : 74 12 : return NO_UID; 75 : } 76 : 77 : 78 : /** \brief Convert a group name in a gid_t. 79 : * 80 : * This function searches for the named group in /etc/group and return the 81 : * corresponding gid_t value. 82 : * 83 : * \param[in] group_name The name of a group to convert to a gid_t. 84 : * 85 : * \return The gid_t of the named group or NO_GID. 86 : */ 87 12 : inline gid_t getgid(std::string const & group_name) 88 : { 89 12 : if(!group_name.empty()) 90 : { 91 2 : struct group const * grp(getgrnam(group_name.c_str())); 92 2 : if(grp != nullptr) 93 : { 94 2 : return grp->gr_gid; 95 : } 96 : } 97 : 98 10 : return NO_GID; 99 : } 100 : 101 : 102 12 : inline int chownnm( 103 : std::string const & path 104 : , uid_t uid 105 : , gid_t gid) 106 : { 107 12 : if(path.empty()) 108 : { 109 0 : throw std::invalid_argument("the path cannot be empty in snap::chownnm()"); 110 : } 111 : 112 12 : if(uid != NO_UID 113 12 : || gid != NO_GID) 114 : { 115 2 : return chown(path.c_str(), uid, gid); 116 : } 117 : 118 : // in case both are undefined (it happens in the mkdir_p() function) 119 : // 120 10 : return 0; 121 : } 122 : 123 : 124 : /** \brief Set the owner and group of a file or directory. 125 : * 126 : * This function determines the user identifier and group identifier 127 : * from the specified names and use them to call chown(). 128 : * 129 : * The function can fail if an identifier for the user or group names 130 : * cannot be determined. 131 : * 132 : * The function may fail if the path is invalid or permissions do not 133 : * allow for ownership modifications. 134 : * 135 : * \param[in] path The path to the file or directory to change. 136 : * \param[in] user_name The name of the user. 137 : * \param[in] group_name The name of the group. 138 : * 139 : * \return 0 if chown succeeded, 140 : * -1 if an error occurs (i.e. permissions denied, unknown user/group) 141 : * and errno is set accordingly. 142 : */ 143 12 : inline int chownnm( 144 : std::string const & path 145 : , std::string const & user_name 146 : , std::string const & group_name) 147 : { 148 12 : return chownnm(path, getuid(user_name), getgid(group_name)); 149 : } 150 : 151 : 152 : inline int chownnm( 153 : std::string const & path 154 : , uid_t uid 155 : , std::string const & group_name) 156 : { 157 : return chownnm(path, uid, getgid(group_name)); 158 : } 159 : 160 : 161 : inline int chownnm( 162 : std::string const & path 163 : , std::string const & user_name 164 : , gid_t gid) 165 : { 166 : return chownnm(path, getuid(user_name), gid); 167 : } 168 : 169 : 170 : 171 : } // namespace snapdev 172 : // vim: ts=4 sw=4 et