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

Generated by: LCOV version 2.0-1