replace obsolete call to ftime(3)
[libi2ncommon] / src / userfunc.cpp
1 /*
2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
4
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
7
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
13
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
16
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
19 */
20 /** @file
21  * @brief provides wrapper and tools for (system) user and group information.
22  *
23  * @copyright Intra2net AG
24  *
25  * @license commercial
26  *
27  * (c) Copyright 2007-2008 by Intra2net AG
28  */
29
30 #include "userfunc.hpp"
31
32 #include <algorithm>
33 #include <fstream>
34
35 #include <unistd.h>
36 #include <signal.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39 #include <dirent.h>
40 #include <pwd.h>
41 #include <grp.h>
42
43 #include <boost/scoped_array.hpp>
44
45 namespace I2n
46 {
47
48 namespace
49 {
50
51 /*
52 ** tool functions
53 */
54
55 bool copy_data ( struct passwd* from, User& to )
56 {
57    to.clear();
58    if (!from) return false;
59    to.Name =       from->pw_name;
60    to.Password =   from->pw_passwd;
61    to.Uid =        from->pw_uid;
62    to.Gid =        from->pw_gid;
63    to.Gecos =      from->pw_gecos;
64    to.Homedir =    from->pw_dir;
65    to.Shell =      from->pw_shell;
66    return true;
67 } // eo copy_data(struct passwd*,Passwd&)
68
69
70 bool copy_data ( struct group* from , Group& to)
71 {
72    to.clear();
73    if (!from) return false;
74    to.Name =       from->gr_name;
75    to.Password =   from->gr_passwd;
76    to.Gid =        from->gr_gid;
77    to.Members.clear();
78    for ( char **ptr= from->gr_mem;
79          ptr && *ptr;
80          ++ptr)
81    {
82       to.Members.push_back ( *ptr );
83    }
84    return true;
85 } // eo copy_data(struct group*,Group&)
86
87
88 } // eo namespace <anonymous>
89
90
91 /*************************************************************************\
92 \*************************************************************************/
93
94 /*
95 ** implementation of User
96 */
97
98 User::User()
99 : Uid ((uid_t)-1)
100 , Gid ((gid_t)-1)
101 {
102 } // User::User()
103
104
105 /**
106  * @brief constructs and fills with user data.
107  * @param name the name of the user to search for.
108  */
109 User::User(const std::string& name)
110 {
111    get_user(name,*this);
112 } // eo User::User(const std::string&)
113
114
115 /**
116  * @brief constructs and fills with user data.
117  * @param name the name of the user to search for.
118  */
119 User::User(const char* name)
120 {
121    get_user(std::string (name),*this);
122 } // eo User::User(const char*)
123
124
125 /**
126  * @brief constructs and fills with user data.
127  * @param uid the uid of the user to search for.
128  */
129 User::User(uid_t uid)
130 {
131    get_user(uid,*this);
132    this->Uid = uid;
133 } // eo User::User(uid_t)
134
135
136
137 /**
138  * @brief clears the data.
139  */
140 void User::clear()
141 {
142    Name.clear();
143    Password.clear();
144    Uid= (uid_t)-1;
145    Gid= (gid_t)-1;
146    Gecos.clear();
147    Homedir.clear();
148    Shell.clear();
149 } // eo User::clear()
150
151
152 /**
153  * @brief returns if the structure content looks ok.
154  * @return @a true if the content looks ok.
155  *
156  * This functions checks if mandatory values are existing.
157  * @note It does not check if content is consistent with any system database!
158  */
159 bool User::is_valid() const
160 {
161    return (Uid != (uid_t)-1) and (Gid != (gid_t)-1)
162           and not Name.empty()
163           ;
164 } // eo User::is_valid() const
165
166
167 /*
168 ** implementation of Group
169 */
170
171
172 Group::Group()
173 : Gid ((gid_t)-1)
174 {
175 } // eo Group::Group()
176
177
178 /**
179  * @brief constructs and fills with group data.
180  * @param name the name of the group to search for.
181  */
182 Group::Group(const std::string& name)
183 {
184    get_group(name,*this);
185 } // eo group::Group(const std::strring&)
186
187
188 /**
189  * @brief constructs and fills with group data.
190  * @param name the name of the group to search for.
191  */
192 Group::Group(const char* name)
193 {
194    get_group(std::string (name),*this);
195 } // eo group::Group(const char*)
196
197
198 /**
199  * @brief constructs and fills with group data.
200  * @param gid the gid of the group to search for.
201  */
202 Group::Group(gid_t gid)
203 {
204    get_group(gid,*this);
205    this->Gid= gid;
206 } // eo Group::Group(gid_t);
207
208
209 /**
210  * @brief clears the data.
211  */
212 void Group::clear()
213 {
214    Name.clear();
215    Password.clear();
216    Gid= (gid_t)-1;
217    Members.clear();
218 } // eo Group::clear()
219
220
221 /**
222  * @brief returns if the structure content looks ok.
223  * @return @a true if the content looks ok.
224  *
225  * This functions checks if mandatory values are existing.
226  * @note It does not check if content is consistent with any system database!
227  */
228 bool Group::is_valid() const
229 {
230    return (Gid != (gid_t)-1) and not Name.empty();
231 } // eo Group::is_valid() const
232
233 /**
234  * @brief get the (system) user data by name.
235  * @param[in] name the name of the user to search for.
236  * @param[out] result the user info.
237  * @return @a true iff the user was found and the result structure contains data.
238  */
239 bool get_user(const std::string& name, User& result)
240 {
241    struct passwd pw;
242    struct passwd *pw_ptr= NULL;
243    size_t buffer_size= sysconf (_SC_GETPW_R_SIZE_MAX);
244    boost::scoped_array< char > buffer ( new char[ buffer_size ] );
245
246    int res= ::getpwnam_r(name.c_str(), &pw, buffer.get(), buffer_size, &pw_ptr);
247
248    if (not (0 == res) or not pw_ptr)
249    {
250       return false;
251    }
252
253    return copy_data(pw_ptr, result);
254 } // eo get_user(const std::string&,User&)
255
256
257 /**
258  * @brief get the (system) user data by uid.
259  * @param[in] uid the uid of the user to search for.
260  * @param[out] result the user info.
261  * @return @a true iff the user was found and the result structure contains data.
262  */
263 bool get_user(uid_t uid, User& result)
264 {
265    struct passwd pw;
266    struct passwd *pw_ptr= NULL;
267    size_t buffer_size= sysconf (_SC_GETPW_R_SIZE_MAX);
268    boost::scoped_array< char > buffer ( new char[ buffer_size ] );
269
270    int res= ::getpwuid_r(uid, &pw, buffer.get(), buffer_size, &pw_ptr);
271
272    if (not (0 == res) or not pw_ptr)
273    {
274       return false;
275    }
276
277    return copy_data(pw_ptr, result);
278 } // eo get_user(uid_t,User&)
279
280
281 /**
282  * @brief get user data by name.
283  * @param name name of the user
284  * @return the user data (invalid if user not found or on error).
285  */
286 User get_user(const std::string& name)
287 {
288    User result;
289    get_user(name,result);
290    return result;
291 } // eo get_user(const std::string&)
292
293
294 /**
295  * @brief get user data by uid.
296  * @param uid uid of the user
297  * @return the user data (invalid if user not found or on error).
298  */
299 User get_user(uid_t uid)
300 {
301    User result;
302    get_user(uid,result);
303    return result;
304 } // eo get_user(const std::string&)
305
306
307
308 /**
309  * @brief get the (system) group data by name.
310  * @param[in] name the name of the group to search for.
311  * @param[out] result the group info.
312  * @return @a true iff the group was found and the result structure contains data.
313  */
314 bool get_group (const std::string& name, Group& result)
315 {
316    struct group gr;
317    struct group *gr_ptr= NULL;
318    size_t buffer_size= sysconf (_SC_GETGR_R_SIZE_MAX);
319    boost::scoped_array< char > buffer ( new char[ buffer_size ] );
320
321    int res= ::getgrnam_r(name.c_str(), &gr, buffer.get(), buffer_size, &gr_ptr);
322
323    if (not (0 == res) or not gr_ptr)
324    {
325       return false;
326    }
327
328    return copy_data(gr_ptr, result);
329 } // eo get_group(const std::string&,Group&)
330
331
332 /**
333  * @brief get the (system) group data by gid.
334  * @param[in] gid the gid of the group to search for.
335  * @param[out] result the group info.
336  * @return @a true iff the group was found and the result structure contains data.
337  */
338 bool get_group(gid_t gid, Group& result)
339 {
340    struct group gr;
341    struct group *gr_ptr= NULL;
342    size_t buffer_size= sysconf (_SC_GETGR_R_SIZE_MAX);
343    boost::scoped_array< char > buffer ( new char[ buffer_size ] );
344
345    int res= ::getgrgid_r(gid, &gr, buffer.get(), buffer_size, &gr_ptr);
346
347    if (not (0 == res) or not gr_ptr)
348    {
349       return false;
350    }
351
352    return copy_data(gr_ptr, result);
353 } // eo get_group(const std::string&,Group&)
354
355
356 /**
357  * @brief get group data by name.
358  * @param name name of the group
359  * @return the group data (invalid if group not found or on error).
360  */
361 Group get_group(const std::string& name)
362 {
363    Group result;
364    get_group(name, result);
365    return result;
366 } // eo get_group(const std::string&)
367
368
369 /**
370  * @brief get group data by gid.
371  * @param gid gid of the group
372  * @return the group data (invalid if group not found or on error).
373  */
374 Group get_group(gid_t gid)
375 {
376    Group result;
377    get_group(gid, result);
378    return result;
379 } // eo get_group(const std::string&)
380
381 } // eo namespace I2n