root/native_client_sdk/src/libraries/nacl_io/getdents_helper.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. init_defaults_
  2. init_defaults_
  3. Reset
  4. Initialize
  5. AddDirent

// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "nacl_io/getdents_helper.h"

#include <assert.h>
#include <errno.h>
#include <string.h>

#include <algorithm>

#include "sdk_util/macros.h"

namespace nacl_io {

GetDentsHelper::GetDentsHelper()
    : curdir_ino_(0), parentdir_ino_(0), init_defaults_(false) {
  Initialize();
}

GetDentsHelper::GetDentsHelper(ino_t curdir_ino, ino_t parentdir_ino)
    : curdir_ino_(curdir_ino),
      parentdir_ino_(parentdir_ino),
      init_defaults_(true) {
  Initialize();
}

void GetDentsHelper::Reset() {
  dirents_.clear();
  Initialize();
}

void GetDentsHelper::Initialize() {
  if (init_defaults_) {
    // Add the default entries: "." and ".."
    AddDirent(curdir_ino_, ".", 1);
    AddDirent(parentdir_ino_, "..", 2);
  }
}

void GetDentsHelper::AddDirent(ino_t ino, const char* name, size_t namelen) {
  assert(name != NULL);
  dirents_.push_back(dirent());
  dirent& entry = dirents_.back();
  entry.d_ino = ino;
  entry.d_off = sizeof(dirent);
  entry.d_reclen = sizeof(dirent);

  if (namelen == 0)
    namelen = strlen(name);

  size_t d_name_max = MEMBER_SIZE(dirent, d_name) - 1;  // -1 for \0.
  size_t copylen = std::min(d_name_max, namelen);
  strncpy(&entry.d_name[0], name, copylen);
  entry.d_name[copylen] = 0;
}

Error GetDentsHelper::GetDents(size_t offs,
                               dirent* pdir,
                               size_t size,
                               int* out_bytes) const {
  *out_bytes = 0;

  // If the buffer pointer is invalid, fail
  if (NULL == pdir)
    return EINVAL;

  // If the buffer is too small, fail
  if (size < sizeof(dirent))
    return EINVAL;

  // Force size to a multiple of dirent
  size -= size % sizeof(dirent);

  size_t max = dirents_.size() * sizeof(dirent);
  if (offs >= max) {
    // OK, trying to read past the end.
    return 0;
  }

  if (offs + size >= max)
    size = max - offs;

  memcpy(pdir, reinterpret_cast<const char*>(dirents_.data()) + offs, size);
  *out_bytes = size;
  return 0;
}

}  // namespace nacl_io

/* [<][>][^][v][top][bottom][index][help] */