diff --git a/ChangeLog b/ChangeLog index 4a32be9..c803eff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2024-12-20 Björn Esser + + libnss_tcb: Match interfaces with NSS documention. + According to [1] the interfaces provided should be of return-type + 'enum nss_status', and take 'int *errnop' as the fourth (and last) + parameter. Additionally the returned status values should be + accompanied by a corresponding ERRNO value [2] passed by the errnop + pointer. + [1] https://www.gnu.org/software/libc/manual/html_node/NSS-Module-Function-Internals.html + [2] https://www.gnu.org/software/libc/manual/html_node/NSS-Modules-Interface.html + * libs/nss.c (_nss_tcb_setspent): Adapt return-type and use return + values from documented macro. + (_nss_tcb_endspent): Likewise. + (_nss_tcb_getspnam_r): Adapt return-type, change fourth parameter + to be 'int *errnop', use return values from documented macro, and + set proper errno in errnop before returning. Also check the pointer + to result buffer, set by fgetspent_r(3), to be non-NULL. + (_nss_tcb_getspent_r): Likewise. + 2024-12-18 Björn Esser libnss_tcb: Initialize or rewind dirstream from inside setspent(3). diff --git a/libs/nss.c b/libs/nss.c index 549957a..c0ee708 100644 --- a/libs/nss.c +++ b/libs/nss.c @@ -13,27 +13,27 @@ static __thread DIR *tcbdir = NULL; -int _nss_tcb_setspent(void) +enum nss_status _nss_tcb_setspent(void) { if (!tcbdir) { tcbdir = opendir(TCB_DIR); if (!tcbdir) return NSS_STATUS_UNAVAIL; - return 1; + return NSS_STATUS_SUCCESS; } rewinddir(tcbdir); - return 1; + return NSS_STATUS_SUCCESS; } -int _nss_tcb_endspent(void) +enum nss_status _nss_tcb_endspent(void) { if (tcbdir) { closedir(tcbdir); tcbdir = NULL; } - return 1; + return NSS_STATUS_SUCCESS; } static FILE *tcb_safe_open(const char *file, const char *name) @@ -66,51 +66,76 @@ static FILE *tcb_safe_open(const char *file, const char *name) return f; } -int _nss_tcb_getspnam_r(const char *name, struct spwd *__result_buf, - char *__buffer, size_t __buflen, struct spwd **__result) +enum nss_status _nss_tcb_getspnam_r(const char *name, + struct spwd *__result_buf, char *__buffer, size_t __buflen, int *__errnop) { FILE *f; char *file; int retval, saved_errno; + struct spwd **result_buf_ptr = NULL; - if (asprintf(&file, TCB_FMT, name) < 0) + if (asprintf(&file, TCB_FMT, name) < 0) { + *__errnop = EAGAIN; return NSS_STATUS_TRYAGAIN; + } + f = tcb_safe_open(file, name); free(file); - if (!f) + if (!f) { + *__errnop = ENOENT; return NSS_STATUS_UNAVAIL; + } - retval = fgetspent_r(f, __result_buf, __buffer, __buflen, __result); + retval = fgetspent_r(f, __result_buf, __buffer, + __buflen, result_buf_ptr); saved_errno = errno; fclose(f); errno = saved_errno; - if (!retval) + if (!retval) { + if (!*result_buf_ptr) { + *__errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } + return NSS_STATUS_SUCCESS; + } switch (saved_errno) { case 0: + if (!*result_buf_ptr) { + *__errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } + return NSS_STATUS_SUCCESS; case ENOENT: + *__errnop = ENOENT; return NSS_STATUS_NOTFOUND; + case EAGAIN: + *__errnop = EAGAIN; + return NSS_STATUS_TRYAGAIN; + case ERANGE: + *__errnop = ERANGE; return NSS_STATUS_TRYAGAIN; default: + *__errnop = ENOENT; return NSS_STATUS_UNAVAIL; } } -int _nss_tcb_getspent_r(struct spwd *__result_buf, - char *__buffer, size_t __buflen, struct spwd **__result) +enum nss_status _nss_tcb_getspent_r(struct spwd *__result_buf, + char *__buffer, size_t __buflen, int *__errnop) { struct dirent *result; off_t currpos; int retval, saved_errno; if (!tcbdir) { - errno = ENOENT; + *__errnop = ENOENT; return NSS_STATUS_UNAVAIL; } @@ -123,11 +148,13 @@ int _nss_tcb_getspent_r(struct spwd *__result_buf, closedir(tcbdir); errno = saved_errno; tcbdir = NULL; + *__errnop = ENOENT; return NSS_STATUS_UNAVAIL; } if (!result) { closedir(tcbdir); errno = ENOENT; + *__errnop = ENOENT; tcbdir = NULL; return NSS_STATUS_NOTFOUND; } @@ -136,7 +163,7 @@ int _nss_tcb_getspent_r(struct spwd *__result_buf, !strcmp(result->d_name, "..") || result->d_name[0] == ':'); retval = _nss_tcb_getspnam_r(result->d_name, __result_buf, __buffer, - __buflen, __result); + __buflen, __errnop); switch (retval) { case NSS_STATUS_SUCCESS: