Initialize Tizen 2.3
[framework/web/wrt-commons.git] / modules / 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/wrt_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     char *errstr = NULL;
40     char errbuf[512] = {0,};
41     size_t size = 0;
42     FTS *fts;
43     FTSENT *ftsent;
44     char * const paths[] = { const_cast<char * const>(path.c_str()), NULL };
45
46     if ((fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR, NULL)) == NULL) {
47         //ERROR
48         int error = errno;
49
50 #ifdef _GNU_SOURCE
51         errstr = strerror_r(error, errbuf, sizeof(errbuf));
52 #else
53         strerror_r(error, errbuf, sizeof(errbuf));
54         errstr = errbuf;
55 #endif
56         WrtLogW("%s: fts_open failed with error: %s",
57             __PRETTY_FUNCTION__, errstr);
58         return 0;
59     }
60
61     while ((ftsent = fts_read(fts)) != NULL) {
62         switch (ftsent->fts_info) {
63         case FTS_DP:
64         case FTS_DC:
65             //directory in postorder and directory causing a loop
66             break;
67         case FTS_F:
68         case FTS_D:
69         case FTS_NSOK:
70         case FTS_SL:
71         case FTS_SLNONE:
72         case FTS_DEFAULT:
73             //regular files and other objects that can be counted
74             size += ftsent->fts_statp->st_size;
75             break;
76         case FTS_NS:
77         case FTS_DOT:
78         case FTS_DNR:
79         case FTS_ERR:
80         default:
81 #ifdef _GNU_SOURCE
82             errstr = strerror_r(ftsent->fts_errno, errbuf, sizeof(errbuf));
83 #else
84             strerror_r(ftsent->fts_errno, errbuf, sizeof(errbuf));
85             errstr = errbuf;
86 #endif
87             WrtLogW("%s: traversal failed on file: %s with error: %s",
88                     __PRETTY_FUNCTION__, ftsent->fts_path,
89                     errstr);
90             return 0;
91         }
92     }
93
94     if (fts_close(fts) == -1) {
95         int error = errno;
96 #ifdef _GNU_SOURCE
97         errstr = strerror_r(error, errbuf, sizeof(errbuf));
98 #else
99         strerror_r(error, errbuf, sizeof(errbuf));
100         errstr = errbuf;
101 #endif
102         WrtLogW("%s: fts_close failed with error: %s",
103                 __PRETTY_FUNCTION__, errstr);
104         return 0;
105     }
106
107     return size;
108 }
109
110 namespace {
111 #define DECLARE_PREFIX_STRUCT(name)     \
112     struct Prefix##name                     \
113     {                                       \
114         static std::string get()              \
115         {                                     \
116             return std::string(#name);      \
117         }                                     \
118     };                                      \
119
120 DECLARE_PREFIX_STRUCT(B)
121 DECLARE_PREFIX_STRUCT(KB)
122 DECLARE_PREFIX_STRUCT(MB)
123 DECLARE_PREFIX_STRUCT(GB)
124
125 #undef DECLARE_PREFIX_STRUCT
126
127 const int stepSize = 1024;
128 template<typename ... Rest>
129 struct Pre;
130
131 template<typename Postfix, typename ... Rest>
132 struct Pre<Postfix, Rest ...>
133 {
134     static const double value;
135     static std::string printSize(double fileSize)
136     {
137         if (fileSize >= Pre<Rest ...>::value) {
138             double now = fileSize / Pre<Rest ...>::value;
139             std::ostringstream outputStream;
140             outputStream.setf(std::ios::fixed, std::ios::floatfield);
141             outputStream.precision(2);
142             outputStream << now << Postfix::get();
143             return outputStream.str();
144         } else {
145             return Pre<Rest ...>::printSize(fileSize);
146         }
147     }
148 };
149
150 template<>
151 struct Pre<>
152 {
153     static const double value;
154     static std::string printSize(double /*fileSize*/)
155     {
156         return "0B";
157     }
158 };
159
160 const double Pre<>::value = 1.0;
161 template<typename Postfix, typename ... Params> const double Pre<Postfix,
162                                                                  Params ...>::
163     value(Pre<>::value * stepSize);
164
165 typedef Pre<PrefixGB, PrefixMB, PrefixKB, PrefixB> FolderSizeToStringType;
166 } //anonymous namespace
167
168 DPL::String fromFileSizeString(size_t fileSize)
169 {
170     std::string output =
171         FolderSizeToStringType::printSize(static_cast<double>(fileSize));
172     return DPL::FromUTF8String(output);
173 }
174 } // end of namespace Utils