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,75 @@ 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 ;
100100
101101 /* Disallow potentially-malicious user names */
102102 if (!is_valid_username (name )) {
103- errno = ENOENT ;
103+ /* we don't serve an entry here */
104+ * __errnop = ENOENT ;
104105 return NSS_STATUS_NOTFOUND ;
105106 }
106107
107- if (asprintf (& file , TCB_FMT , name ) < 0 )
108+ if (asprintf (& file , TCB_FMT , name ) < 0 ) {
109+ /* retry, as malloc or another resource has failed */
110+ * __errnop = EAGAIN ;
108111 return NSS_STATUS_TRYAGAIN ;
112+ }
113+
109114 f = tcb_safe_open (file , name );
110115 free (file );
111- if (!f )
112- return errno == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL ;
116+ if (!f ) {
117+ /* $user/shadow not existing */
118+ * __errnop = ENOENT ;
119+ return NSS_STATUS_UNAVAIL ;
120+ }
113121
114- retval = fgetspent_r (f , __result_buf , __buffer , __buflen , __result );
122+ retval = fgetspent_r (f , __result_buf , __buffer ,
123+ __buflen , & __result_buf );
115124 saved_errno = errno ;
116125 fclose (f );
117126 errno = saved_errno ;
118127 if (!retval )
119128 return NSS_STATUS_SUCCESS ;
120129
121- switch (saved_errno ) {
122- case 0 :
123- return NSS_STATUS_SUCCESS ;
124-
130+ /* real error number is retval from fgetspent_r() */
131+ * __errnop = retval ;
132+ switch (retval ) {
125133 case ENOENT :
134+ /* if the file would not exist, we would have already
135+ bailed out with ENOENT/NSS_STATUS_UNAVAIL immediately
136+ after the call to tcb_safe_open() */
126137 return NSS_STATUS_NOTFOUND ;
127138
139+ case EAGAIN :
140+ /* ressources are temporary not available */
141+ return NSS_STATUS_TRYAGAIN ;
142+
128143 case ERANGE :
144+ /* __buffer too small */
129145 return NSS_STATUS_TRYAGAIN ;
130146
131147 default :
148+ /* something serious, but we can't help it */
132149 return NSS_STATUS_UNAVAIL ;
133150 }
134151}
135152
136- int _nss_tcb_getspent_r (struct spwd * __result_buf ,
137- char * __buffer , size_t __buflen , struct spwd * * __result )
153+ enum nss_status _nss_tcb_getspent_r (struct spwd * __result_buf ,
154+ char * __buffer , size_t __buflen , int * __errnop )
138155{
139156 struct dirent * result ;
140157 off_t currpos ;
141158 int retval , saved_errno ;
142159
143160 if (!tcbdir ) {
144- errno = ENOENT ;
161+ /* tcbdir does not exist */
162+ * __errnop = ENOENT ;
145163 return NSS_STATUS_UNAVAIL ;
146164 }
147165
@@ -154,21 +172,26 @@ int _nss_tcb_getspent_r(struct spwd *__result_buf,
154172 closedir (tcbdir );
155173 errno = saved_errno ;
156174 tcbdir = NULL ;
175+ /* cannot iterate tcbdir */
176+ * __errnop = ENOENT ;
157177 return NSS_STATUS_UNAVAIL ;
158178 }
159179 if (!result ) {
160180 closedir (tcbdir );
161- errno = ENOENT ;
181+ errno = saved_errno ;
162182 tcbdir = NULL ;
183+ /* we have no more entries in tcbdir */
184+ * __errnop = ENOENT ;
163185 return NSS_STATUS_NOTFOUND ;
164186 }
165187 errno = saved_errno ;
166188 } while (!strcmp (result -> d_name , "." ) ||
167189 !strcmp (result -> d_name , ".." ) || result -> d_name [0 ] == ':' );
168190
169191 retval = _nss_tcb_getspnam_r (result -> d_name , __result_buf , __buffer ,
170- __buflen , __result );
192+ __buflen , __errnop );
171193
194+ /* __errnop has already been set by _nss_tcb_getspnam_r() */
172195 switch (retval ) {
173196 case NSS_STATUS_SUCCESS :
174197 return NSS_STATUS_SUCCESS ;
0 commit comments