librostlab
1.0.20
|
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: