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: 2026-07-12 15:23:06 Functions: 22.2 % 18 4

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

Generated by: LCOV version 2.0-1