librostlab  1.0.20
rostlab/cxxgrp.h
Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2011 Laszlo Kajan, Technical University of Munich, Germany
00003 
00004     This file is part of librostlab.
00005 
00006     librostlab is free software: you can redistribute it and/or modify
00007     it under the terms of the GNU Lesser General Public License as published by
00008     the Free Software Foundation, either version 3 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU Lesser General Public License for more details.
00015 
00016     You should have received a copy of the GNU Lesser General Public License
00017     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 #ifndef ROSTLAB_CXXGRP
00020 #define ROSTLAB_CXXGRP 1
00021 
00022 #include <boost/format.hpp>
00023 #include <errno.h>
00024 #include <grp.h>
00025 #include <string>
00026 #include <string.h>
00027 #include <sys/types.h>
00028 #include <vector>
00029 
00030 #include "rostlab/rostlab_stdexcept.h"
00031 
00032 namespace bo = boost;
00033 
00034 namespace rostlab {
00035 
00036 struct cxx_group
00037 {
00038   std::string          gr_name;       /* group name */
00039   std::string          gr_passwd;     /* group password */
00040   gid_t           gr_gid;        /* group ID */
00041   std::vector<std::string>  gr_mem;        /* group members */
00042 
00043   inline          cxx_group(){};
00044   inline          cxx_group( const std::string& __gr_name );
00045   inline          cxx_group( const std::string& __gr_name, const std::string& __gr_passwd, gid_t __gr_gid, const std::vector<std::string>& __gr_mem ) :
00046                     gr_name(__gr_name), gr_passwd(__gr_passwd), gr_gid(__gr_gid), gr_mem(__gr_mem) {};
00047   inline          cxx_group( const std::string& __gr_name, const std::string& __gr_passwd, gid_t __gr_gid, char** __gr_mem ) :
00048                     gr_name(__gr_name), gr_passwd(__gr_passwd), gr_gid(__gr_gid) { while(*__gr_mem) gr_mem.push_back( *__gr_mem++ ); };
00049 };
00050 
00051 class gid_not_found_error : public runtime_error { public: gid_not_found_error( const std::string& what ) : runtime_error(what) {} };
00052 class gname_not_found_error : public runtime_error { public: gname_not_found_error( const std::string& what ) : runtime_error(what) {} };
00053 
00054 // namespace functions
00055 inline std::string     getgrgid_r( gid_t __gid );
00056 inline std::string     getgrgid_r( gid_t __gid, cxx_group& __group );
00057 inline gid_t      getgrnam_r( const std::string& __gname );
00058 inline gid_t      getgrnam_r( const std::string& __gname, struct cxx_group& __group );
00059 
00060 
00061 inline            cxx_group::cxx_group( const std::string& __gr_name )
00062 {
00063   rostlab::getgrnam_r( __gr_name, *this );
00064 };
00065 
00066 inline std::string     getgrgid_r( gid_t __gid, cxx_group& __group )
00067 {
00068   struct group gbuf;
00069   struct group *gbufp;
00070 
00071   size_t buflen = sysconf( _SC_GETGR_R_SIZE_MAX );
00072   char* buf = static_cast<char *>( malloc(buflen) ); if(!buf) throw runtime_error( bo::str( bo::format("failed to allocate %d bytes") % buflen ) );
00073 
00074   try{
00075     int _errno;
00076     do {
00077       _errno = ::getgrgid_r( __gid, &gbuf, buf, buflen, &gbufp );
00078       if( _errno == ERANGE ) // too small buffer
00079       {
00080         buflen *= 2;
00081         buf = static_cast<char *>( realloc( buf, buflen ) ); if(!buf) throw runtime_error( bo::str( bo::format("failed to allocate %d bytes") % buflen ) );
00082       }
00083       else if( _errno ) throw runtime_error( bo::str( bo::format("failed to getgrgid_r '%d': %s") % __gid % strerror( errno ) ) );
00084     } while( _errno );
00085 
00086     if( gbufp == NULL ) throw gid_not_found_error( bo::str( bo::format("gid '%d' not found") % __gid ) );
00087 
00088     __group = cxx_group( gbuf.gr_name, gbuf.gr_passwd, gbuf.gr_gid, gbuf.gr_mem );
00089   }
00090   catch(...)
00091   {
00092     free(buf);
00093     throw;
00094   }
00095   free(buf); buf = NULL;
00096 
00097   return __group.gr_name;
00098 }
00099 
00100 inline std::string     getgrgid_r( gid_t __gid )
00101 {
00102   struct cxx_group        grp;
00103   return getgrgid_r( __gid, grp );
00104 }
00105 
00106 
00107 inline gid_t    getgrnam_r( const std::string& __gname, struct cxx_group& __group )
00108 {
00109   struct group gbuf;
00110   struct group *gbufp;
00111 
00112   size_t buflen = sysconf( _SC_GETGR_R_SIZE_MAX );
00113   char* buf = static_cast<char *>( malloc(buflen) ); if(!buf) throw runtime_error( bo::str( bo::format("failed to allocate %d bytes") % buflen ) );
00114 
00115   try{
00116     int _errno;
00117     do {
00118       _errno = ::getgrnam_r( __gname.c_str(), &gbuf, buf, buflen, &gbufp );
00119       if( _errno == ERANGE ) // too small buffer
00120       {
00121         buflen *= 2;
00122         buf = static_cast<char *>( realloc( buf, buflen ) ); if(!buf) throw runtime_error( bo::str( bo::format("failed to allocate %d bytes") % buflen ) );
00123       }
00124       else if( _errno ) throw runtime_error( bo::str( bo::format("failed to getgrnam_r '%s': %s") % __gname % strerror( errno ) ) );
00125     } while( _errno );
00126 
00127     if( gbufp == NULL ) throw gname_not_found_error( bo::str( bo::format("gname '%s' not found") % __gname ) );
00128 
00129     __group = cxx_group( gbuf.gr_name, gbuf.gr_passwd, gbuf.gr_gid, gbuf.gr_mem );
00130   }
00131   catch(...)
00132   {
00133     free(buf);
00134     throw;
00135   }
00136   free(buf); buf = NULL;
00137 
00138   return gbuf.gr_gid;
00139 }
00140 
00141 
00142 inline gid_t    getgrnam_r( const std::string& __gname )
00143 {
00144   struct cxx_group        grp;
00145   return getgrnam_r( __gname, grp );
00146 }
00147 
00148 }; // namespace rostlab
00149 
00150 #endif // ROSTLAB_CXXGRP
00151 // vim:et:ai:ts=2:
 All Classes Namespaces Files Functions Variables Typedefs