LCOV - code coverage report
Current view: top level - pulsecore - usergroup.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 64 106 60.4 %
Date: 2012-07-17 Functions: 10 11 90.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 20 70 28.6 %

           Branch data     Line data    Source code
       1                 :            : /***
       2                 :            :   This file is part of PulseAudio.
       3                 :            : 
       4                 :            :   Copyright 2009 Ted Percival
       5                 :            : 
       6                 :            :   PulseAudio is free software; you can redistribute it and/or modify
       7                 :            :   it under the terms of the GNU Lesser General Public License as
       8                 :            :   published by the Free Software Foundation; either version 2.1 of the
       9                 :            :   License, or (at your option) any later version.
      10                 :            : 
      11                 :            :   PulseAudio is distributed in the hope that it will be useful, but
      12                 :            :   WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      14                 :            :   Lesser General Public License for more details.
      15                 :            : 
      16                 :            :   You should have received a copy of the GNU Lesser General Public
      17                 :            :   License along with PulseAudio; if not, write to the Free Software
      18                 :            :   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
      19                 :            :   USA.
      20                 :            : ***/
      21                 :            : 
      22                 :            : #ifdef HAVE_CONFIG_H
      23                 :            : #include <config.h>
      24                 :            : #endif
      25                 :            : 
      26                 :            : #include <sys/types.h>
      27                 :            : #include <errno.h>
      28                 :            : 
      29                 :            : #ifdef HAVE_PWD_H
      30                 :            : #include <pwd.h>
      31                 :            : #endif
      32                 :            : 
      33                 :            : #ifdef HAVE_GRP_H
      34                 :            : #include <grp.h>
      35                 :            : #endif
      36                 :            : 
      37                 :            : #include <pulse/xmalloc.h>
      38                 :            : #include <pulsecore/macro.h>
      39                 :            : 
      40                 :            : #include "usergroup.h"
      41                 :            : 
      42                 :            : #ifdef HAVE_GRP_H
      43                 :            : 
      44                 :            : /* Returns a suitable starting size for a getgrnam_r() or getgrgid_r() buffer,
      45                 :            :    plus the size of a struct group.
      46                 :            :  */
      47                 :          2 : static size_t starting_getgr_buflen(void) {
      48                 :            :     size_t full_size;
      49                 :            :     long n;
      50                 :            : #ifdef _SC_GETGR_R_SIZE_MAX
      51                 :          2 :     n = sysconf(_SC_GETGR_R_SIZE_MAX);
      52                 :            : #else
      53                 :            :     n = -1;
      54                 :            : #endif
      55         [ -  + ]:          2 :     if (n <= 0)
      56                 :          0 :         n = 512;
      57                 :            : 
      58                 :          2 :     full_size = (size_t) n + sizeof(struct group);
      59                 :            : 
      60         [ -  + ]:          2 :     if (full_size < (size_t) n) /* check for integer overflow */
      61                 :          2 :         return (size_t) n;
      62                 :            : 
      63                 :            :     return full_size;
      64                 :            : }
      65                 :            : 
      66                 :            : /* Returns a suitable starting size for a getpwnam_r() or getpwuid_r() buffer,
      67                 :            :    plus the size of a struct passwd.
      68                 :            :  */
      69                 :          2 : static size_t starting_getpw_buflen(void) {
      70                 :            :     long n;
      71                 :            :     size_t full_size;
      72                 :            : 
      73                 :            : #ifdef _SC_GETPW_R_SIZE_MAX
      74                 :          2 :     n = sysconf(_SC_GETPW_R_SIZE_MAX);
      75                 :            : #else
      76                 :            :     n = -1;
      77                 :            : #endif
      78         [ -  + ]:          2 :     if (n <= 0)
      79                 :          0 :         n = 512;
      80                 :            : 
      81                 :          2 :     full_size = (size_t) n + sizeof(struct passwd);
      82                 :            : 
      83         [ -  + ]:          2 :     if (full_size < (size_t) n) /* check for integer overflow */
      84                 :          2 :         return (size_t) n;
      85                 :            : 
      86                 :            :     return full_size;
      87                 :            : }
      88                 :            : 
      89                 :            : /* Given a memory allocation (*bufptr) and its length (*buflenptr),
      90                 :            :    double the size of the allocation, updating the given buffer and length
      91                 :            :    arguments. This function should be used in conjunction with the pa_*alloc
      92                 :            :    and pa_xfree functions.
      93                 :            : 
      94                 :            :    Unlike realloc(), this function does *not* retain the original buffer's
      95                 :            :    contents.
      96                 :            : 
      97                 :            :    Returns 0 on success, nonzero on error. The error cause is indicated by
      98                 :            :    errno.
      99                 :            :  */
     100                 :          0 : static int expand_buffer_trashcontents(void **bufptr, size_t *buflenptr) {
     101                 :            :     size_t newlen;
     102                 :            : 
     103 [ #  # ][ #  # ]:          0 :     if (!bufptr || !*bufptr || !buflenptr) {
     104                 :          0 :         errno = EINVAL;
     105                 :          0 :         return -1;
     106                 :            :     }
     107                 :            : 
     108                 :          0 :     newlen = *buflenptr * 2;
     109                 :            : 
     110         [ #  # ]:          0 :     if (newlen < *buflenptr) {
     111                 :          0 :         errno = EOVERFLOW;
     112                 :          0 :         return -1;
     113                 :            :     }
     114                 :            : 
     115                 :            :     /* Don't bother retaining memory contents; free & alloc anew */
     116                 :          0 :     pa_xfree(*bufptr);
     117                 :            : 
     118                 :          0 :     *bufptr = pa_xmalloc(newlen);
     119                 :          0 :     *buflenptr = newlen;
     120                 :            : 
     121                 :          0 :     return 0;
     122                 :            : }
     123                 :            : 
     124                 :            : #ifdef HAVE_GETGRGID_R
     125                 :            : /* Thread-safe getgrgid() replacement.
     126                 :            :    Returned value should be freed using pa_getgrgid_free() when the caller is
     127                 :            :    finished with the returned group data.
     128                 :            : 
     129                 :            :    API is the same as getgrgid(), errors are indicated by a NULL return;
     130                 :            :    consult errno for the error cause (zero it before calling).
     131                 :            :  */
     132                 :          1 : struct group *pa_getgrgid_malloc(gid_t gid) {
     133                 :            :     size_t buflen, getgr_buflen;
     134                 :            :     int err;
     135                 :            :     void *buf;
     136                 :            :     void *getgr_buf;
     137                 :          1 :     struct group *result = NULL;
     138                 :            : 
     139                 :          1 :     buflen = starting_getgr_buflen();
     140                 :          1 :     buf = pa_xmalloc(buflen);
     141                 :            : 
     142                 :          1 :     getgr_buflen = buflen - sizeof(struct group);
     143                 :          1 :     getgr_buf = (char *)buf + sizeof(struct group);
     144                 :            : 
     145         [ -  + ]:          1 :     while ((err = getgrgid_r(gid, (struct group *)buf, getgr_buf, getgr_buflen, &result)) == ERANGE) {
     146         [ #  # ]:          0 :         if (expand_buffer_trashcontents(&buf, &buflen))
     147                 :            :             break;
     148                 :            : 
     149                 :          0 :         getgr_buflen = buflen - sizeof(struct group);
     150                 :          0 :         getgr_buf = (char *)buf + sizeof(struct group);
     151                 :            :     }
     152                 :            : 
     153 [ +  - ][ -  + ]:          1 :     if (err || !result) {
     154                 :          0 :         result = NULL;
     155         [ #  # ]:          0 :         if (buf) {
     156                 :          0 :             pa_xfree(buf);
     157                 :          0 :             buf = NULL;
     158                 :            :         }
     159                 :            :     }
     160                 :            : 
     161 [ -  + ][ #  # ]:          1 :     pa_assert(result == buf || result == NULL);
     162                 :            : 
     163                 :          1 :     return result;
     164                 :            : }
     165                 :            : 
     166                 :          1 : void pa_getgrgid_free(struct group *grp) {
     167                 :          1 :     pa_xfree(grp);
     168                 :          1 : }
     169                 :            : 
     170                 :            : #else /* !HAVE_GETGRGID_R */
     171                 :            : 
     172                 :            : struct group *pa_getgrgid_malloc(gid_t gid) {
     173                 :            :     return getgrgid(gid);
     174                 :            : }
     175                 :            : 
     176                 :            : void pa_getgrgid_free(struct group *grp) {
     177                 :            :     /* nothing */
     178                 :            :     return;
     179                 :            : }
     180                 :            : 
     181                 :            : #endif /* !HAVE_GETGRGID_R */
     182                 :            : 
     183                 :            : #ifdef HAVE_GETGRNAM_R
     184                 :            : /* Thread-safe getgrnam() function.
     185                 :            :    Returned value should be freed using pa_getgrnam_free() when the caller is
     186                 :            :    finished with the returned group data.
     187                 :            : 
     188                 :            :    API is the same as getgrnam(), errors are indicated by a NULL return;
     189                 :            :    consult errno for the error cause (zero it before calling).
     190                 :            :  */
     191                 :          1 : struct group *pa_getgrnam_malloc(const char *name) {
     192                 :            :     size_t buflen, getgr_buflen;
     193                 :            :     int err;
     194                 :            :     void *buf;
     195                 :            :     void *getgr_buf;
     196                 :          1 :     struct group *result = NULL;
     197                 :            : 
     198                 :          1 :     buflen = starting_getgr_buflen();
     199                 :          1 :     buf = pa_xmalloc(buflen);
     200                 :            : 
     201                 :          1 :     getgr_buflen = buflen - sizeof(struct group);
     202                 :          1 :     getgr_buf = (char *)buf + sizeof(struct group);
     203                 :            : 
     204         [ -  + ]:          1 :     while ((err = getgrnam_r(name, (struct group *)buf, getgr_buf, getgr_buflen, &result)) == ERANGE) {
     205         [ #  # ]:          0 :         if (expand_buffer_trashcontents(&buf, &buflen))
     206                 :            :             break;
     207                 :            : 
     208                 :          0 :         getgr_buflen = buflen - sizeof(struct group);
     209                 :          0 :         getgr_buf = (char *)buf + sizeof(struct group);
     210                 :            :     }
     211                 :            : 
     212 [ +  - ][ -  + ]:          1 :     if (err || !result) {
     213                 :          0 :         result = NULL;
     214         [ #  # ]:          0 :         if (buf) {
     215                 :          0 :             pa_xfree(buf);
     216                 :          0 :             buf = NULL;
     217                 :            :         }
     218                 :            :     }
     219                 :            : 
     220 [ -  + ][ #  # ]:          1 :     pa_assert(result == buf || result == NULL);
     221                 :            : 
     222                 :          1 :     return result;
     223                 :            : }
     224                 :            : 
     225                 :          1 : void pa_getgrnam_free(struct group *group) {
     226                 :          1 :     pa_xfree(group);
     227                 :          1 : }
     228                 :            : 
     229                 :            : #else /* !HAVE_GETGRNAM_R */
     230                 :            : 
     231                 :            : struct group *pa_getgrnam_malloc(const char *name) {
     232                 :            :     return getgrnam(name);
     233                 :            : }
     234                 :            : 
     235                 :            : void pa_getgrnam_free(struct group *group) {
     236                 :            :     /* nothing */
     237                 :            :     return;
     238                 :            : }
     239                 :            : 
     240                 :            : #endif /* HAVE_GETGRNAM_R */
     241                 :            : 
     242                 :            : #endif /* HAVE_GRP_H */
     243                 :            : 
     244                 :            : #ifdef HAVE_PWD_H
     245                 :            : 
     246                 :            : #ifdef HAVE_GETPWNAM_R
     247                 :            : /* Thread-safe getpwnam() function.
     248                 :            :    Returned value should be freed using pa_getpwnam_free() when the caller is
     249                 :            :    finished with the returned passwd data.
     250                 :            : 
     251                 :            :    API is the same as getpwnam(), errors are indicated by a NULL return;
     252                 :            :    consult errno for the error cause (zero it before calling).
     253                 :            :  */
     254                 :          1 : struct passwd *pa_getpwnam_malloc(const char *name) {
     255                 :            :     size_t buflen, getpw_buflen;
     256                 :            :     int err;
     257                 :            :     void *buf;
     258                 :            :     void *getpw_buf;
     259                 :          1 :     struct passwd *result = NULL;
     260                 :            : 
     261                 :          1 :     buflen = starting_getpw_buflen();
     262                 :          1 :     buf = pa_xmalloc(buflen);
     263                 :            : 
     264                 :          1 :     getpw_buflen = buflen - sizeof(struct passwd);
     265                 :          1 :     getpw_buf = (char *)buf + sizeof(struct passwd);
     266                 :            : 
     267         [ -  + ]:          1 :     while ((err = getpwnam_r(name, (struct passwd *)buf, getpw_buf, getpw_buflen, &result)) == ERANGE) {
     268         [ #  # ]:          0 :         if (expand_buffer_trashcontents(&buf, &buflen))
     269                 :            :             break;
     270                 :            : 
     271                 :          0 :         getpw_buflen = buflen - sizeof(struct passwd);
     272                 :          0 :         getpw_buf = (char *)buf + sizeof(struct passwd);
     273                 :            :     }
     274                 :            : 
     275 [ +  - ][ -  + ]:          1 :     if (err || !result) {
     276                 :          0 :         result = NULL;
     277         [ #  # ]:          0 :         if (buf) {
     278                 :          0 :             pa_xfree(buf);
     279                 :          0 :             buf = NULL;
     280                 :            :         }
     281                 :            :     }
     282                 :            : 
     283 [ -  + ][ #  # ]:          1 :     pa_assert(result == buf || result == NULL);
     284                 :            : 
     285                 :          1 :     return result;
     286                 :            : }
     287                 :            : 
     288                 :          1 : void pa_getpwnam_free(struct passwd *passwd) {
     289                 :          1 :     pa_xfree(passwd);
     290                 :          1 : }
     291                 :            : 
     292                 :            : #else /* !HAVE_GETPWNAM_R */
     293                 :            : 
     294                 :            : struct passwd *pa_getpwnam_malloc(const char *name) {
     295                 :            :     return getpwnam(name);
     296                 :            : }
     297                 :            : 
     298                 :            : void pa_getpwnam_free(struct passwd *passwd) {
     299                 :            :     /* nothing */
     300                 :            :     return;
     301                 :            : }
     302                 :            : 
     303                 :            : #endif /* !HAVE_GETPWNAM_R */
     304                 :            : 
     305                 :            : #ifdef HAVE_GETPWUID_R
     306                 :            : /* Thread-safe getpwuid() function.
     307                 :            :    Returned value should be freed using pa_getpwuid_free() when the caller is
     308                 :            :    finished with the returned group data.
     309                 :            : 
     310                 :            :    API is the same as getpwuid(), errors are indicated by a NULL return;
     311                 :            :    consult errno for the error cause (zero it before calling).
     312                 :            :  */
     313                 :          1 : struct passwd *pa_getpwuid_malloc(uid_t uid) {
     314                 :            :     size_t buflen, getpw_buflen;
     315                 :            :     int err;
     316                 :            :     void *buf;
     317                 :            :     void *getpw_buf;
     318                 :          1 :     struct passwd *result = NULL;
     319                 :            : 
     320                 :          1 :     buflen = starting_getpw_buflen();
     321                 :          1 :     buf = pa_xmalloc(buflen);
     322                 :            : 
     323                 :          1 :     getpw_buflen = buflen - sizeof(struct passwd);
     324                 :          1 :     getpw_buf = (char *)buf + sizeof(struct passwd);
     325                 :            : 
     326         [ -  + ]:          1 :     while ((err = getpwuid_r(uid, (struct passwd *)buf, getpw_buf, getpw_buflen, &result)) == ERANGE) {
     327         [ #  # ]:          0 :         if (expand_buffer_trashcontents(&buf, &buflen))
     328                 :            :             break;
     329                 :            : 
     330                 :          0 :         getpw_buflen = buflen - sizeof(struct passwd);
     331                 :          0 :         getpw_buf = (char *)buf + sizeof(struct passwd);
     332                 :            :     }
     333                 :            : 
     334 [ +  - ][ -  + ]:          1 :     if (err || !result) {
     335                 :          0 :         result = NULL;
     336         [ #  # ]:          0 :         if (buf) {
     337                 :          0 :             pa_xfree(buf);
     338                 :          0 :             buf = NULL;
     339                 :            :         }
     340                 :            :     }
     341                 :            : 
     342 [ -  + ][ #  # ]:          1 :     pa_assert(result == buf || result == NULL);
     343                 :            : 
     344                 :          1 :     return result;
     345                 :            : }
     346                 :            : 
     347                 :          1 : void pa_getpwuid_free(struct passwd *passwd) {
     348                 :          1 :     pa_xfree(passwd);
     349                 :          1 : }
     350                 :            : 
     351                 :            : #else /* !HAVE_GETPWUID_R */
     352                 :            : 
     353                 :            : struct passwd *pa_getpwuid_malloc(uid_t uid) {
     354                 :            :     return getpwuid(uid);
     355                 :            : }
     356                 :            : 
     357                 :            : void pa_getpwuid_free(struct passwd *passwd) {
     358                 :            :     /* nothing */
     359                 :            :     return;
     360                 :            : }
     361                 :            : 
     362                 :            : #endif /* !HAVE_GETPWUID_R */
     363                 :            : 
     364                 :            : #endif /* HAVE_PWD_H */

Generated by: LCOV version 1.9