summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Thomson <martin.thomson@gmail.com>2016-03-10 20:08:04 +1100
committerMartin Thomson <martin.thomson@gmail.com>2016-03-10 20:08:04 +1100
commit6b279ab67347db6eb4d75679d704fe3cc37c7395 (patch)
tree7b5e3586b2e68dbb3854d129fd7aa078f9ed44e6
parentffef05d80bdbd79b706d344772168d310a0d4d50 (diff)
downloadnss-hg-6b279ab67347db6eb4d75679d704fe3cc37c7395.tar.gz
Bug 1254334 - Use readdir instead of readdir_r, r=emaldona, sr=rrelyea
-rw-r--r--lib/freebl/unix_rand.c55
1 files changed, 23 insertions, 32 deletions
diff --git a/lib/freebl/unix_rand.c b/lib/freebl/unix_rand.c
index d2baa6dcd..d773b193b 100644
--- a/lib/freebl/unix_rand.c
+++ b/lib/freebl/unix_rand.c
@@ -1054,26 +1054,16 @@ ReadFileOK(char *dir, char *file)
*
* return 1 if it's time to reset the fileToRead (no more files to read).
*/
-int ReadOneFile(int fileToRead)
+static int
+ReadOneFile(int fileToRead)
{
char *dir = "/etc";
DIR *fd = opendir(dir);
int resetCount = 0;
-#ifdef SOLARIS
- /* grumble, Solaris does not define struct dirent to be the full length */
- typedef union {
- unsigned char space[sizeof(struct dirent) + MAXNAMELEN];
- struct dirent dir;
- } dirent_hack;
- dirent_hack entry, firstEntry;
-
-#define entry_dir entry.dir
-#else
- struct dirent entry, firstEntry;
-#define entry_dir entry
-#endif
-
- int i, error = -1;
+ struct dirent *entry;
+ char firstName[NAME_MAX + 1];
+ const char *name = NULL;
+ int i;
if (fd == NULL) {
dir = PR_GetEnvSecure("HOME");
@@ -1085,33 +1075,34 @@ int ReadOneFile(int fileToRead)
return 1;
}
+ firstName[0] = '\0';
for (i=0; i <= fileToRead; i++) {
- struct dirent *result = NULL;
do {
- error = readdir_r(fd, &entry_dir, &result);
- } while (error == 0 && result != NULL &&
- !ReadFileOK(dir,&result->d_name[0]));
- if (error != 0 || result == NULL) {
+ /* readdir() isn't guaranteed to be thread safe on every platform;
+ * this code assumes the same directory isn't read concurrently.
+ * This usage is confirmed safe on Linux, see bug 1254334. */
+ entry = readdir(fd);
+ } while (entry != NULL && !ReadFileOK(dir, &entry->d_name[0]));
+ if (entry == NULL) {
resetCount = 1; /* read to the end, start again at the beginning */
- if (i != 0) {
+ if (firstName[0]) {
/* ran out of entries in the directory, use the first one */
- entry = firstEntry;
- error = 0;
- break;
+ name = firstName;
}
- /* if i== 0, there were no readable entries in the directory */
break;
}
- if (i==0) {
- /* save the first entry in case we run out of entries */
- firstEntry = entry;
+ name = entry->d_name;
+ if (i == 0) {
+ /* copy the name of the first in case we run out of entries */
+ PORT_Assert(PORT_Strlen(name) <= NAME_MAX);
+ PORT_Strncpy(firstName, name, NAME_MAX);
+ firstName[NAME_MAX] = '\0';
}
}
- if (error == 0) {
+ if (name) {
char filename[PATH_MAX];
- int count = snprintf(filename, sizeof filename,
- "%s/%s",dir, &entry_dir.d_name[0]);
+ int count = snprintf(filename, sizeof(filename), "%s/%s",dir, name);
if (count >= 1) {
ReadSingleFile(filename);
}