LCOV - code coverage report
Current view: top level - okssystem/src - User.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 17.4 % 132 23
Test Date: 2025-12-21 13:07:08 Functions: 22.2 % 18 4

            Line data    Source code
       1              : /*
       2              :  *  User.cxx
       3              :  *  OksSystem
       4              :  *
       5              :  *  Created by Matthias Wiesmann on 03.02.05.
       6              :  *  Copyright 2005 CERN. All rights reserved.
       7              :  *
       8              :  */
       9              : 
      10              : #include <pwd.h> 
      11              : 
      12              : #include <iostream>
      13              : #include <sstream>
      14              : 
      15              : #include "ers/ers.hpp"
      16              : 
      17              : #include "okssystem/User.hpp"
      18              : #include "okssystem/exceptions.hpp"
      19              : 
      20              : const OksSystem::User OksSystem::User::ROOT(0);
      21              : 
      22           16 : OksSystem::User::User() throw() {
      23           16 :     m_user_id = ::getuid();
      24           16 : } // User
      25              : 
      26           54 : OksSystem::User::User(uid_t user_id) throw() {
      27           54 :     m_user_id = user_id;
      28           54 : } // User
      29              : 
      30            0 : OksSystem::User::User(const std::string &s_name) {
      31              :   
      32            0 :   errno = 0;
      33            0 :   long bufSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
      34              :   
      35            0 :   if(bufSize == -1) {
      36            0 :     if(errno == 0) {
      37              :       bufSize = 1024;
      38              :     } else {  
      39            0 :       std::string message = "with argument _SC_GETPW_R_SIZE_MAX while getting info about user " + s_name;
      40            0 :       throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "sysconf", message.c_str());
      41            0 :     }
      42              :   }
      43              : 
      44            0 :   struct passwd pwd;
      45            0 :   struct passwd *result;  
      46            0 :   char* buf = new char[bufSize];
      47            0 :   errno = 0;
      48            0 :   int res = ::getpwnam_r(s_name.c_str(), &pwd, buf, bufSize, &result);
      49            0 :   if(res == 0) {
      50            0 :     if(result != 0) {
      51            0 :       m_user_id = result->pw_uid;
      52              :     } else {
      53            0 :       delete[] buf;
      54            0 :       std::string eMsg = "User " + s_name + " not found";
      55            0 :       throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "getpwnam_r", eMsg.c_str());
      56            0 :     }
      57              :   } else {
      58            0 :     delete[] buf;
      59            0 :     std::string message = "while getting info about user " + s_name;
      60            0 :     throw OksSystem::OksSystemCallIssue(ERS_HERE, res, "getpwnam_r", message.c_str());
      61            0 :   }
      62            0 :   delete[] buf;
      63              : 
      64            0 :   m_user_name = s_name;
      65            0 : } // User
      66              : 
      67            0 : OksSystem::User::User(const User &other) throw() {
      68            0 :     m_user_id = other.m_user_id;
      69            0 :     m_user_name = other.m_user_name;
      70            0 : } // User
      71              : 
      72              : // Operators
      73              : // =========
      74              : 
      75              : 
      76            0 : OksSystem::User::operator uid_t() const throw() {
      77            0 :     return m_user_id;
      78              : } // uid_t
      79              : 
      80            0 : OksSystem::User::operator std::string() const {
      81            0 :     return name();
      82              : } // string 
      83              : 
      84            0 : OksSystem::User::operator const char *() const {
      85            0 :     if (m_user_name.empty()) { resolve();}
      86            0 :     return m_user_name.c_str();
      87              : } // char* 
      88              : 
      89              : //  Methods
      90              : // =========
      91              : 
      92              : /** Returns the user_id for user
      93              :   * \return user-id
      94              :   */
      95              : 
      96            0 : uid_t OksSystem::User::identity() const throw() { 
      97            0 :     return m_user_id;
      98              : } // identity
      99              : 
     100              : /** This method is responsible for filling in the mutable fields of the class 
     101              :   * when needed, this is done by calling the \c getpwuid function, 
     102              :   * all fields of the object are then filled in. 
     103              :   * \throw OksSystem::OksSystemCallIssue if the user information cannot be found 
     104              :   */
     105              : 
     106            0 : void OksSystem::User::resolve() const {
     107              :   
     108            0 :   errno = 0;
     109            0 :   long bufSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
     110              :   
     111            0 :   if(bufSize == -1) {
     112            0 :     if(errno == 0) {
     113              :       bufSize = 1024;
     114              :     } else {  
     115            0 :       std::ostringstream message;
     116            0 :       message << "with argument _SC_GETPW_R_SIZE_MAX while getting info about user with id " << m_user_id;
     117            0 :       throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "sysconf", message.str().c_str()); 
     118            0 :     }
     119              :   }
     120              : 
     121            0 :   struct passwd pwd;
     122            0 :   struct passwd *result;
     123            0 :   char* buf = new char[bufSize];
     124            0 :   errno = 0;
     125            0 :   int res = ::getpwuid_r(m_user_id, &pwd, buf, bufSize, &result);
     126            0 :   if(res == 0) {
     127            0 :     if(result != 0) {
     128            0 :       m_user_name = std::string(result->pw_name);
     129            0 :       m_user_home = std::string(result->pw_dir);
     130            0 :       m_user_real_name = std::string(result->pw_gecos);
     131              :     } else {
     132            0 :       delete[] buf;      
     133            0 :       std::ostringstream eMsg;
     134            0 :       eMsg << "User " << m_user_id << " not found";
     135            0 :       throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "getpwuid_r", eMsg.str().c_str());
     136            0 :     }
     137              :   } else {
     138            0 :     delete[] buf;
     139            0 :     std::ostringstream message;
     140            0 :     message << "while getting info about user with id " << m_user_id;
     141            0 :     throw OksSystem::OksSystemCallIssue(ERS_HERE, res, "getpwnam_r", message.str().c_str());
     142            0 :   }
     143            0 :   delete[] buf;
     144              : 
     145            0 : } // 
     146              : 
     147              : /** This method is the same as \c resolve() but does not throw exceptions.
     148              :   * Instead the method silently fails 
     149              :   * \see OksSystem::User::resolve()
     150              :   */
     151              : 
     152           16 : void OksSystem::User::resolve_safe() const throw() {
     153              : 
     154           16 :   errno = 0;
     155           16 :   long bufSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
     156              :   
     157           16 :   if(bufSize == -1) {
     158            0 :     if(errno == 0) {
     159              :       bufSize = 1024;
     160              :     } else {  
     161            0 :       m_user_name = "unknown";
     162            0 :       m_user_home = "unknown";
     163            0 :       m_user_real_name = "unknown"; 
     164            0 :       return;
     165              :     }
     166              :   }
     167              : 
     168           16 :   struct passwd pwd;
     169           16 :   struct passwd *result;
     170           16 :   char* buf = new char[bufSize];
     171           16 :   int res = ::getpwuid_r(m_user_id, &pwd, buf, bufSize, &result);
     172           16 :   if(res == 0) {
     173           16 :     if(result != 0) {
     174           16 :       m_user_name = std::string(result->pw_name);
     175           16 :       m_user_home = std::string(result->pw_dir);
     176           16 :       m_user_real_name = std::string(result->pw_gecos);
     177              :     } else {
     178            0 :       m_user_name = "unknown";
     179            0 :       m_user_home = "unknown";
     180            0 :       m_user_real_name = "unknown";      
     181              :     }
     182              :   } else {
     183            0 :     m_user_name = "unknown";
     184            0 :     m_user_home = "unknown";
     185            0 :     m_user_real_name = "unknown"; 
     186              :   }
     187           16 :   delete[] buf;
     188              : 
     189              : } // resolve_safe
     190              : 
     191              : /** Gets the (short) name of the user 
     192              :   * \return the name of user 
     193              :   */
     194              : 
     195            0 : const std::string & OksSystem::User::name() const {
     196            0 :     if (m_user_name.empty()) { resolve();}
     197            0 :     return m_user_name;
     198              : } // name
     199              : 
     200              : /** Gets the (short) name of the user - no error is thrown in case of problem
     201              :   * \return the name of user
     202              :   */
     203              : 
     204           16 : const std::string &  OksSystem::User::name_safe() const throw() {
     205           16 :     if (m_user_name.empty()) { resolve_safe(); }
     206           16 :     return m_user_name;
     207              : } // name
     208              : 
     209              : /** Gets the home directory of the user 
     210              :   * \return path to home directory 
     211              :   */
     212              : 
     213            0 : const std::string & OksSystem::User::home() const {
     214            0 :     if (m_user_home.empty()) { resolve();}
     215            0 :     return m_user_home;
     216              : } // home
     217              : 
     218              : /** Gets the 'real name' of the user 
     219              :   * \return real name 
     220              :   */
     221              : 
     222            0 : const std::string & OksSystem::User::real_name() const {
     223            0 :     if (m_user_real_name.empty()) { resolve();}
     224            0 :     return m_user_real_name;
     225              : } // real_name
     226              : 
     227              : /** Sets the user-identity of the current process to this user. 
     228              :   * This method will only succeed if the current user has sufficient privileges to changed uids
     229              :   * (typically because the current user is root). 
     230              :   */
     231              : 
     232            0 : void OksSystem::User::setuid() const {
     233            0 :     const int status = ::setuid(m_user_id); 
     234            0 :     if (status<0) {
     235            0 :       std::ostringstream message;
     236            0 :       message << "while setting the effective user ID to " << m_user_id << "(" << this->name_safe() << ")";
     237            0 :       throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "setuid", message.str().c_str() );
     238            0 :     } 
     239            0 : } // setuid
     240              : 
     241              : 
     242              : /** Output operator, writes username followed by uid between parenthesis
     243              :   * \param stream the stream to write into
     244              :   * \param user the user object to write
     245              :   * \return parameter stream
     246              :   */
     247              : 
     248            0 : std::ostream& operator<<(std::ostream& stream, const OksSystem::User& user) throw() {
     249            0 :     unsigned int i = (unsigned int) user.identity(); 
     250            0 :     const std::string name = user.name_safe();
     251            0 :     stream << name << '(' << i << ')';
     252            0 :     return stream;
     253            0 : } // operator<< 
     254              : 
     255              : /** Equality operator 
     256              :   * \param a first user to compare 
     257              :   * \param b second user to compare 
     258              :   * \return true if they are equal
     259              :   */
     260              : 
     261            0 : bool operator ==(const OksSystem::User &a, const OksSystem::User &b)  throw() {
     262            0 :     return a.identity() == b.identity();
     263              : } // 
     264              : 
     265              : /** Inequality operator 
     266              :  * \param a first user to compare 
     267              :  * \param b second user to compare 
     268              :  * \return true if they are not equal
     269              :  */
     270              : 
     271            0 : bool operator !=(const OksSystem::User &a, const OksSystem::User &b)  throw() {
     272            0 :     return a.identity() != b.identity();
     273              : } // 
     274              : 
     275              : 
        

Generated by: LCOV version 2.0-1