522216a9ba2d08b7c142c152e50bc6481bd4aba0
[framework/web/wrt-commons.git] / modules_mobile / utils / src / folder_size.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  *
18  * @file        folder_size.cpp
19  * @author      Jaroslaw Osmanski (j.osmanski@samsung.com)
20  * @version     1.0
21  * @brief       Implementation for function calculating directory size
22  */
23 #include <stddef.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fts.h>
28
29 #include <sstream>
30 #include <vector>
31
32 #include <dpl/log/log.h>
33 #include <dpl/foreach.h>
34 #include <dpl/utils/folder_size.h>
35
36 namespace Utils {
37 size_t getFolderSize(const std::string& path)
38 {
39     size_t size = 0;
40     FTS *fts;
41     FTSENT *ftsent;
42     char * const paths[] = { const_cast<char * const>(path.c_str()), NULL };
43
44     if ((fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR, NULL)) == NULL) {
45         //ERROR
46         int error = errno;
47         LogWarning(__PRETTY_FUNCTION__ << ": fts_open failed with error: "
48                                        << strerror(error));
49         return 0;
50     }
51
52     while ((ftsent = fts_read(fts)) != NULL) {
53         switch (ftsent->fts_info) {
54         case FTS_DP:
55         case FTS_DC:
56             //directory in postorder and directory causing a loop
57             break;
58         case FTS_F:
59         case FTS_D:
60         case FTS_NSOK:
61         case FTS_SL:
62         case FTS_SLNONE:
63         case FTS_DEFAULT:
64             //regular files and other objects that can be counted
65             size += ftsent->fts_statp->st_size;
66             break;
67         case FTS_NS:
68         case FTS_DOT:
69         case FTS_DNR:
70         case FTS_ERR:
71         default:
72             LogWarning(__PRETTY_FUNCTION__
73                        << ": traversal failed on file: "
74                        << ftsent->fts_path
75                        << " with error: "
76                        << strerror(ftsent->fts_errno));
77             return 0;
78         }
79     }
80
81     if (fts_close(fts) == -1) {
82         int error = errno;
83         LogWarning(__PRETTY_FUNCTION__ << ": fts_close failed with error: "
84                                        << strerror(error));
85         return 0;
86     }
87
88     return size;
89 }
90
91 namespace {
92 #define DECLARE_PREFIX_STRUCT(name)     \
93     struct Prefix##name                     \
94     {                                       \
95         static std::string get()              \
96         {                                     \
97             return std::string(#name);      \
98         }                                     \
99     };                                      \
100
101 DECLARE_PREFIX_STRUCT(B)
102 DECLARE_PREFIX_STRUCT(KB)
103 DECLARE_PREFIX_STRUCT(MB)
104 DECLARE_PREFIX_STRUCT(GB)
105
106 #undef DECLARE_PREFIX_STRUCT
107
108 const int stepSize = 1024;
109 template<typename ... Rest>
110 struct Pre;
111
112 template<typename Postfix, typename ... Rest>
113 struct Pre<Postfix, Rest ...>
114 {
115     static const double value;
116     static std::string printSize(double fileSize)
117     {
118         if (fileSize >= Pre<Rest ...>::value) {
119             double now = fileSize / Pre<Rest ...>::value;
120             std::ostringstream outputStream;
121             outputStream.setf(std::ios::fixed, std::ios::floatfield);
122             outputStream.precision(2);
123             outputStream << now << Postfix::get();
124             return outputStream.str();
125         } else {
126             return Pre<Rest ...>::printSize(fileSize);
127         }
128     }
129 };
130
131 template<>
132 struct Pre<>
133 {
134     static const double value;
135     static std::string printSize(double /*fileSize*/)
136     {
137         return "0B";
138     }
139 };
140
141 const double Pre<>::value = 1.0;
142 template<typename Postfix, typename ... Params> const double Pre<Postfix,
143                                                                  Params ...>::
144     value(Pre<>::value * stepSize);
145
146 typedef Pre<PrefixGB, PrefixMB, PrefixKB, PrefixB> FolderSizeToStringType;
147 } //anonymous namespace
148
149 DPL::String fromFileSizeString(size_t fileSize)
150 {
151     std::string output =
152         FolderSizeToStringType::printSize(static_cast<double>(fileSize));
153     return DPL::FromUTF8String(output);
154 }
155 } // end of namespace Utils