Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / libraries / nacl_io / getdents_helper.cc
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 "nacl_io/log.h"
14
15 #include "sdk_util/macros.h"
16
17 namespace nacl_io {
18
19 GetDentsHelper::GetDentsHelper()
20     : curdir_ino_(0), parentdir_ino_(0), init_defaults_(false) {
21   Initialize();
22 }
23
24 GetDentsHelper::GetDentsHelper(ino_t curdir_ino, ino_t parentdir_ino)
25     : curdir_ino_(curdir_ino),
26       parentdir_ino_(parentdir_ino),
27       init_defaults_(true) {
28   Initialize();
29 }
30
31 void GetDentsHelper::Reset() {
32   dirents_.clear();
33   Initialize();
34 }
35
36 void GetDentsHelper::Initialize() {
37   if (init_defaults_) {
38     // Add the default entries: "." and ".."
39     AddDirent(curdir_ino_, ".", 1);
40     AddDirent(parentdir_ino_, "..", 2);
41   }
42 }
43
44 void GetDentsHelper::AddDirent(ino_t ino, const char* name, size_t namelen) {
45   assert(name != NULL);
46   dirents_.push_back(dirent());
47   dirent& entry = dirents_.back();
48   entry.d_ino = ino;
49   entry.d_off = sizeof(dirent);
50   entry.d_reclen = sizeof(dirent);
51
52   if (namelen == 0)
53     namelen = strlen(name);
54
55   size_t d_name_max = MEMBER_SIZE(dirent, d_name) - 1;  // -1 for \0.
56   size_t copylen = std::min(d_name_max, namelen);
57   strncpy(&entry.d_name[0], name, copylen);
58   entry.d_name[copylen] = 0;
59 }
60
61 Error GetDentsHelper::GetDents(size_t offs,
62                                dirent* pdir,
63                                size_t size,
64                                int* out_bytes) const {
65   *out_bytes = 0;
66
67   // If the buffer pointer is invalid, fail
68   if (NULL == pdir) {
69     LOG_TRACE("dirent pointer is NULL.");
70     return EINVAL;
71   }
72
73   // If the buffer is too small, fail
74   if (size < sizeof(dirent)) {
75     LOG_TRACE("dirent buffer size is too small: %d < %d", size, sizeof(dirent));
76     return EINVAL;
77   }
78
79   // Force size to a multiple of dirent
80   size -= size % sizeof(dirent);
81
82   size_t max = dirents_.size() * sizeof(dirent);
83   if (offs >= max) {
84     // OK, trying to read past the end.
85     return 0;
86   }
87
88   if (offs + size >= max)
89     size = max - offs;
90
91   memcpy(pdir, reinterpret_cast<const char*>(dirents_.data()) + offs, size);
92   *out_bytes = size;
93   return 0;
94 }
95
96 }  // namespace nacl_io