Browse Source

don't set errno or return an error when getspnam[_r] finds no entry

this case is specified as success with a null result, rather than an
error, and errno is not to be set on success.
Rich Felker 6 years ago
parent
commit
9db81b862d
2 changed files with 9 additions and 3 deletions
  1. 2 1
      src/passwd/getspnam.c
  2. 7 2
      src/passwd/getspnam_r.c

+ 2 - 1
src/passwd/getspnam.c

@@ -8,10 +8,11 @@ struct spwd *getspnam(const char *name)
 	static char *line;
 	struct spwd *res;
 	int e;
+	int orig_errno = errno;
 
 	if (!line) line = malloc(LINE_LIM);
 	if (!line) return 0;
 	e = getspnam_r(name, &sp, line, LINE_LIM, &res);
-	if (e) errno = e;
+	errno = e ? e : orig_errno;
 	return res;
 }

+ 7 - 2
src/passwd/getspnam_r.c

@@ -67,6 +67,7 @@ int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct
 	size_t k, l = strlen(name);
 	int skip = 0;
 	int cs;
+	int orig_errno = errno;
 
 	*res = 0;
 
@@ -94,7 +95,11 @@ int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct
 		}
 	} else {
 		f = fopen("/etc/shadow", "rbe");
-		if (!f) return errno;
+		if (!f) {
+			if (errno != ENOENT && errno != ENOTDIR)
+				return errno;
+			return 0;
+		}
 	}
 
 	pthread_cleanup_push(cleanup, f);
@@ -113,6 +118,6 @@ int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct
 		break;
 	}
 	pthread_cleanup_pop(1);
-	if (rv) errno = rv;
+	errno = rv ? rv : orig_errno;
 	return rv;
 }