• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "nacl_io/getdents_helper.h"
6 
7 #include <assert.h>
8 #include <errno.h>
9 #include <string.h>
10 
11 #include <algorithm>
12 
13 #include "sdk_util/macros.h"
14 
15 namespace nacl_io {
16 
GetDentsHelper()17 GetDentsHelper::GetDentsHelper()
18     : curdir_ino_(0), parentdir_ino_(0), init_defaults_(false) {
19   Initialize();
20 }
21 
GetDentsHelper(ino_t curdir_ino,ino_t parentdir_ino)22 GetDentsHelper::GetDentsHelper(ino_t curdir_ino, ino_t parentdir_ino)
23     : curdir_ino_(curdir_ino),
24       parentdir_ino_(parentdir_ino),
25       init_defaults_(true) {
26   Initialize();
27 }
28 
Reset()29 void GetDentsHelper::Reset() {
30   dirents_.clear();
31   Initialize();
32 }
33 
Initialize()34 void GetDentsHelper::Initialize() {
35   if (init_defaults_) {
36     // Add the default entries: "." and ".."
37     AddDirent(curdir_ino_, ".", 1);
38     AddDirent(parentdir_ino_, "..", 2);
39   }
40 }
41 
AddDirent(ino_t ino,const char * name,size_t namelen)42 void GetDentsHelper::AddDirent(ino_t ino, const char* name, size_t namelen) {
43   assert(name != NULL);
44   dirents_.push_back(dirent());
45   dirent& entry = dirents_.back();
46   entry.d_ino = ino;
47   entry.d_off = sizeof(dirent);
48   entry.d_reclen = sizeof(dirent);
49 
50   if (namelen == 0)
51     namelen = strlen(name);
52 
53   size_t d_name_max = MEMBER_SIZE(dirent, d_name) - 1;  // -1 for \0.
54   size_t copylen = std::min(d_name_max, namelen);
55   strncpy(&entry.d_name[0], name, copylen);
56   entry.d_name[copylen] = 0;
57 }
58 
GetDents(size_t offs,dirent * pdir,size_t size,int * out_bytes) const59 Error GetDentsHelper::GetDents(size_t offs,
60                                dirent* pdir,
61                                size_t size,
62                                int* out_bytes) const {
63   *out_bytes = 0;
64 
65   // If the buffer pointer is invalid, fail
66   if (NULL == pdir)
67     return EINVAL;
68 
69   // If the buffer is too small, fail
70   if (size < sizeof(dirent))
71     return EINVAL;
72 
73   // Force size to a multiple of dirent
74   size -= size % sizeof(dirent);
75 
76   size_t max = dirents_.size() * sizeof(dirent);
77   if (offs >= max) {
78     // OK, trying to read past the end.
79     return 0;
80   }
81 
82   if (offs + size >= max)
83     size = max - offs;
84 
85   memcpy(pdir, reinterpret_cast<const char*>(dirents_.data()) + offs, size);
86   *out_bytes = size;
87   return 0;
88 }
89 
90 }  // namespace nacl_io
91