Home | History | Annotate | Download | only in nacl_io
      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