1313
1414static __thread DIR * tcbdir = NULL ;
1515
16- int _nss_tcb_setspent (void )
16+ enum nss_status _nss_tcb_setspent (void )
1717{
1818 if (!tcbdir ) {
1919 tcbdir = opendir (TCB_DIR );
2020 if (!tcbdir )
2121 return NSS_STATUS_UNAVAIL ;
2222
23- return 1 ;
23+ return NSS_STATUS_SUCCESS ;
2424 }
2525
2626 rewinddir (tcbdir );
27- return 1 ;
27+ return NSS_STATUS_SUCCESS ;
2828}
2929
30- int _nss_tcb_endspent (void )
30+ enum nss_status _nss_tcb_endspent (void )
3131{
3232 if (tcbdir ) {
3333 closedir (tcbdir );
3434 tcbdir = NULL ;
3535 }
36- return 1 ;
36+ return NSS_STATUS_SUCCESS ;
3737}
3838
3939/******************************************************************************
@@ -91,57 +91,76 @@ static FILE *tcb_safe_open(const char *file, const char *name)
9191 return f ;
9292}
9393
94- int _nss_tcb_getspnam_r (const char * name , struct spwd * __result_buf ,
95- char * __buffer , size_t __buflen , struct spwd * * __result )
94+ enum nss_status _nss_tcb_getspnam_r (const char * name ,
95+ struct spwd * __result_buf , char * __buffer , size_t __buflen , int * __errnop )
9696{
9797 FILE * f ;
9898 char * file ;
9999 int retval , saved_errno ;
100+ struct spwd * * result_buf_ptr = NULL ;
100101
101102 /* Disallow potentially-malicious user names */
102103 if (!is_valid_username (name )) {
103- errno = ENOENT ;
104+ /* we don't serve an entry here */
105+ * __errnop = ENOENT ;
104106 return NSS_STATUS_NOTFOUND ;
105107 }
106108
107- if (asprintf (& file , TCB_FMT , name ) < 0 )
109+ if (asprintf (& file , TCB_FMT , name ) < 0 ) {
110+ /* retry, as malloc or another resource has failed */
111+ * __errnop = EAGAIN ;
108112 return NSS_STATUS_TRYAGAIN ;
113+ }
114+
109115 f = tcb_safe_open (file , name );
110116 free (file );
111- if (!f )
112- return errno == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL ;
117+ if (!f ) {
118+ /* $user/shadow not existing */
119+ * __errnop = ENOENT ;
120+ return NSS_STATUS_UNAVAIL ;
121+ }
113122
114- retval = fgetspent_r (f , __result_buf , __buffer , __buflen , __result );
123+ retval = fgetspent_r (f , __result_buf , __buffer ,
124+ __buflen , result_buf_ptr );
115125 saved_errno = errno ;
116126 fclose (f );
117127 errno = saved_errno ;
118128 if (!retval )
119129 return NSS_STATUS_SUCCESS ;
120130
121- switch (saved_errno ) {
122- case 0 :
123- return NSS_STATUS_SUCCESS ;
124-
131+ /* real error number is retval from fgetspent_r() */
132+ * __errnop = retval ;
133+ switch (retval ) {
125134 case ENOENT :
135+ /* if the file would not exist, we would have already
136+ bailed out with ENOENT/NSS_STATUS_UNAVAIL immediately
137+ after the call to tcb_safe_open() */
126138 return NSS_STATUS_NOTFOUND ;
127139
140+ case EAGAIN :
141+ /* ressources are temporary not available */
142+ return NSS_STATUS_TRYAGAIN ;
143+
128144 case ERANGE :
145+ /* __buffer too small */
129146 return NSS_STATUS_TRYAGAIN ;
130147
131148 default :
149+ /* something serious, but we can't help it */
132150 return NSS_STATUS_UNAVAIL ;
133151 }
134152}
135153
136- int _nss_tcb_getspent_r (struct spwd * __result_buf ,
137- char * __buffer , size_t __buflen , struct spwd * * __result )
154+ enum nss_status _nss_tcb_getspent_r (struct spwd * __result_buf ,
155+ char * __buffer , size_t __buflen , int * __errnop )
138156{
139157 struct dirent * result ;
140158 off_t currpos ;
141159 int retval , saved_errno ;
142160
143161 if (!tcbdir ) {
144- errno = ENOENT ;
162+ /* tcbdir does not exist */
163+ * __errnop = ENOENT ;
145164 return NSS_STATUS_UNAVAIL ;
146165 }
147166
@@ -154,21 +173,26 @@ int _nss_tcb_getspent_r(struct spwd *__result_buf,
154173 closedir (tcbdir );
155174 errno = saved_errno ;
156175 tcbdir = NULL ;
176+ /* cannot iterate tcbdir */
177+ * __errnop = ENOENT ;
157178 return NSS_STATUS_UNAVAIL ;
158179 }
159180 if (!result ) {
160181 closedir (tcbdir );
161- errno = ENOENT ;
182+ errno = saved_errno ;
162183 tcbdir = NULL ;
184+ /* we have no more entries in tcbdir */
185+ * __errnop = ENOENT ;
163186 return NSS_STATUS_NOTFOUND ;
164187 }
165188 errno = saved_errno ;
166189 } while (!strcmp (result -> d_name , "." ) ||
167190 !strcmp (result -> d_name , ".." ) || result -> d_name [0 ] == ':' );
168191
169192 retval = _nss_tcb_getspnam_r (result -> d_name , __result_buf , __buffer ,
170- __buflen , __result );
193+ __buflen , __errnop );
171194
195+ /* __errnop has already been set by _nss_tcb_getspnam_r() */
172196 switch (retval ) {
173197 case NSS_STATUS_SUCCESS :
174198 return NSS_STATUS_SUCCESS ;
0 commit comments