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