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 17 GetDentsHelper::GetDentsHelper() 18 : curdir_ino_(0), parentdir_ino_(0), init_defaults_(false) { 19 Initialize(); 20 } 21 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 29 void GetDentsHelper::Reset() { 30 dirents_.clear(); 31 Initialize(); 32 } 33 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 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 59 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