librostlab  1.0.20
 All Classes Namespaces Files Functions Variables Typedefs
cxxgrp.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 Laszlo Kajan, Technical University of Munich, Germany
3 
4  This file is part of librostlab.
5 
6  librostlab is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #ifndef ROSTLAB_CXXGRP
20 #define ROSTLAB_CXXGRP 1
21 
22 #include <boost/format.hpp>
23 #include <errno.h>
24 #include <grp.h>
25 #include <string>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <vector>
29 
31 
32 namespace bo = boost;
33 
34 namespace rostlab {
35 
36 struct cxx_group
37 {
38  std::string gr_name; /* group name */
39  std::string gr_passwd; /* group password */
40  gid_t gr_gid; /* group ID */
41  std::vector<std::string> gr_mem; /* group members */
42 
43  inline cxx_group(){};
44  inline cxx_group( const std::string& __gr_name );
45  inline cxx_group( const std::string& __gr_name, const std::string& __gr_passwd, gid_t __gr_gid, const std::vector<std::string>& __gr_mem ) :
46  gr_name(__gr_name), gr_passwd(__gr_passwd), gr_gid(__gr_gid), gr_mem(__gr_mem) {};
47  inline cxx_group( const std::string& __gr_name, const std::string& __gr_passwd, gid_t __gr_gid, char** __gr_mem ) :
48  gr_name(__gr_name), gr_passwd(__gr_passwd), gr_gid(__gr_gid) { while(*__gr_mem) gr_mem.push_back( *__gr_mem++ ); };
49 };
50 
51 class gid_not_found_error : public runtime_error { public: gid_not_found_error( const std::string& what ) : runtime_error(what) {} };
52 class gname_not_found_error : public runtime_error { public: gname_not_found_error( const std::string& what ) : runtime_error(what) {} };
53 
54 // namespace functions
55 inline std::string getgrgid_r( gid_t __gid );
56 inline std::string getgrgid_r( gid_t __gid, cxx_group& __group );
57 inline gid_t getgrnam_r( const std::string& __gname );
58 inline gid_t getgrnam_r( const std::string& __gname, struct cxx_group& __group );
59 
60 
61 inline cxx_group::cxx_group( const std::string& __gr_name )
62 {
63  rostlab::getgrnam_r( __gr_name, *this );
64 };
65 
66 inline std::string getgrgid_r( gid_t __gid, cxx_group& __group )
67 {
68  struct group gbuf;
69  struct group *gbufp;
70 
71  size_t buflen = sysconf( _SC_GETGR_R_SIZE_MAX );
72  char* buf = static_cast<char *>( malloc(buflen) ); if(!buf) throw runtime_error( bo::str( bo::format("failed to allocate %d bytes") % buflen ) );
73 
74  try{
75  int _errno;
76  do {
77  _errno = ::getgrgid_r( __gid, &gbuf, buf, buflen, &gbufp );
78  if( _errno == ERANGE ) // too small buffer
79  {
80  buflen *= 2;
81  buf = static_cast<char *>( realloc( buf, buflen ) ); if(!buf) throw runtime_error( bo::str( bo::format("failed to allocate %d bytes") % buflen ) );
82  }
83  else if( _errno ) throw runtime_error( bo::str( bo::format("failed to getgrgid_r '%d': %s") % __gid % strerror( errno ) ) );
84  } while( _errno );
85 
86  if( gbufp == NULL ) throw gid_not_found_error( bo::str( bo::format("gid '%d' not found") % __gid ) );
87 
88  __group = cxx_group( gbuf.gr_name, gbuf.gr_passwd, gbuf.gr_gid, gbuf.gr_mem );
89  }
90  catch(...)
91  {
92  free(buf);
93  throw;
94  }
95  free(buf); buf = NULL;
96 
97  return __group.gr_name;
98 }
99 
100 inline std::string getgrgid_r( gid_t __gid )
101 {
102  struct cxx_group grp;
103  return getgrgid_r( __gid, grp );
104 }
105 
106 
107 inline gid_t getgrnam_r( const std::string& __gname, struct cxx_group& __group )
108 {
109  struct group gbuf;
110  struct group *gbufp;
111 
112  size_t buflen = sysconf( _SC_GETGR_R_SIZE_MAX );
113  char* buf = static_cast<char *>( malloc(buflen) ); if(!buf) throw runtime_error( bo::str( bo::format("failed to allocate %d bytes") % buflen ) );
114 
115  try{
116  int _errno;
117  do {
118  _errno = ::getgrnam_r( __gname.c_str(), &gbuf, buf, buflen, &gbufp );
119  if( _errno == ERANGE ) // too small buffer
120  {
121  buflen *= 2;
122  buf = static_cast<char *>( realloc( buf, buflen ) ); if(!buf) throw runtime_error( bo::str( bo::format("failed to allocate %d bytes") % buflen ) );
123  }
124  else if( _errno ) throw runtime_error( bo::str( bo::format("failed to getgrnam_r '%s': %s") % __gname % strerror( errno ) ) );
125  } while( _errno );
126 
127  if( gbufp == NULL ) throw gname_not_found_error( bo::str( bo::format("gname '%s' not found") % __gname ) );
128 
129  __group = cxx_group( gbuf.gr_name, gbuf.gr_passwd, gbuf.gr_gid, gbuf.gr_mem );
130  }
131  catch(...)
132  {
133  free(buf);
134  throw;
135  }
136  free(buf); buf = NULL;
137 
138  return gbuf.gr_gid;
139 }
140 
141 
142 inline gid_t getgrnam_r( const std::string& __gname )
143 {
144  struct cxx_group grp;
145  return getgrnam_r( __gname, grp );
146 }
147 
148 }; // namespace rostlab
149 
150 #endif // ROSTLAB_CXXGRP
151 // vim:et:ai:ts=2: