1 //===--- Implementation of a platform independent Dir data structure ------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "dir.h"
10 
11 #include <stdlib.h>
12 
13 namespace __llvm_libc {
14 
open(const char * path)15 Dir *Dir::open(const char *path) {
16   int fd = platform_opendir(path);
17   if (fd < 0)
18     return nullptr;
19 
20   Dir *dir = reinterpret_cast<Dir *>(malloc(sizeof(Dir)));
21   dir->fd = fd;
22   dir->readptr = 0;
23   dir->fillsize = 0;
24   Mutex::init(&dir->mutex, false, false, false);
25 
26   return dir;
27 }
28 
read()29 struct ::dirent *Dir::read() {
30   MutexLock lock(&mutex);
31   if (readptr >= fillsize) {
32     fillsize = platform_fetch_dirents(
33         fd, cpp::MutableArrayRef<uint8_t>(buffer, BUFSIZE));
34     if (fillsize == 0)
35       return nullptr;
36     readptr = 0;
37   }
38   struct ::dirent *d = reinterpret_cast<struct ::dirent *>(buffer + readptr);
39 #ifdef __unix__
40   // The d_reclen field is available on Linux but not required by POSIX.
41   readptr += d->d_reclen;
42 #else
43   // Other platforms have to implement how the read pointer is to be updated.
44 #error "DIR read pointer update is missing."
45 #endif
46   return d;
47 }
48 
close()49 int Dir::close() {
50   {
51     MutexLock lock(&mutex);
52     if (!platform_closedir(fd))
53       return -1;
54   }
55   free(this);
56   return 0;
57 }
58 
59 } // namespace __llvm_libc
60