87646f754d73548ca72cd8260d7f43f7f08fd6fe
[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
24 #include <string.h>
25 #include <dirent.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28
29 #include <sstream>
30 #include <vector>
31
32 #include <dpl/log/log.h>
33 #include <dpl/foreach.h>
34 #include <folder_size.h>
35
36 namespace Utils {
37 namespace {
38
39 size_t getObjectSize(const std::string& path)
40 {
41     struct stat tmp;
42
43     if (stat(path.c_str(), &tmp) == -1) {
44         LogError("Failed to open file" << path);
45         return 0;
46     }
47     //it is not a file nor a directory
48     //not counting
49     if (!S_ISDIR(tmp.st_mode) && !S_ISREG(tmp.st_mode)) {
50         LogWarning("Not a regular file nor a directory: " << path);
51         return 0;
52     }
53     return tmp.st_size;
54 }
55 }
56
57 size_t getFolderSize(const std::string& path)
58 {
59     size_t size = 0;
60
61     DIR *dir;
62     std::vector<std::string> localDirs;
63     if ((dir=opendir(path.c_str())) == NULL) {
64         LogError("Cannot open dir " << path);
65         return 0;
66     }
67     struct dirent* el;
68     while ((el = readdir(dir)) != 0) {
69         if (strcmp(el->d_name, ".") == 0 || strcmp(el->d_name, "..") == 0) {
70             continue;
71         }
72         struct stat tmp;
73         std::string local = path + el->d_name;
74         if (stat(local.c_str(), &tmp) == -1) {
75             LogError("Failed to open file " << local);
76             char* errstring = strerror(errno);
77             LogError("Reason: " << errstring);
78             continue;
79         }
80
81         size += getObjectSize(local);
82         if (S_ISDIR(tmp.st_mode)) {
83             localDirs.push_back(local + "/");
84         }
85     }
86
87     closedir(dir);
88
89     FOREACH (localDir, localDirs) {
90         size += getFolderSize(*localDir);
91     }
92
93     return size;
94 }
95
96
97
98
99
100 namespace {
101 #define DECLARE_PREFIX_STRUCT(name)     \
102 struct Prefix##name                     \
103 {                                       \
104   static std::string get()              \
105   {                                     \
106         return std::string(#name);      \
107   }                                     \
108 };                                      \
109
110 DECLARE_PREFIX_STRUCT(B)
111 DECLARE_PREFIX_STRUCT(KB)
112 DECLARE_PREFIX_STRUCT(MB)
113 DECLARE_PREFIX_STRUCT(GB)
114
115 #undef DECLARE_PREFIX_STRUCT
116
117
118 const int stepSize = 1024;
119 template<typename... Rest>
120 struct Pre;
121
122 template<typename Postfix, typename... Rest>
123 struct Pre<Postfix, Rest...>
124 {
125     static const double value = Pre<Rest...>::value * stepSize;
126     static std::string printSize(double fileSize)
127     {
128         if(fileSize >= Pre<Rest...>::value) {
129             double now = fileSize / Pre<Rest...>::value;
130             std::ostringstream outputStream;
131             outputStream.setf(std::ios::fixed, std::ios::floatfield);
132             outputStream.precision(2);
133             outputStream << now << Postfix::get();
134             return outputStream.str();
135         } else {
136             return Pre<Rest...>::printSize(fileSize);
137         }
138
139     }
140 };
141
142 template<>
143 struct Pre<>
144 {
145         static const double value;
146         static std::string printSize(double /*fileSize*/)
147         {
148                 return "0B";
149         }
150
151 };
152 const double Pre<>::value = 1.0;
153
154 typedef Pre<PrefixGB, PrefixMB, PrefixKB, PrefixB> FolderSizeToStringType;
155 } //anonymous namespace
156
157
158 DPL::String fromFileSizeString(size_t fileSize)
159 {
160
161     std::string output =
162         FolderSizeToStringType::printSize(static_cast<double>(fileSize));
163     return DPL::FromUTF8String(output);
164 }
165
166 } // end of namespace Utils