]> pilppa.org Git - libplp.git/blob - src/FileUtil.cc
8b905e6729d4958dad96ff74303a83991133f3eb
[libplp.git] / src / FileUtil.cc
1 /*
2  * FileUtil.cc
3  *
4  *  Created on: Mar 5, 2011
5  *      Author: lamikr
6  */
7
8 #include <algorithm>
9 #include <string>
10 #include <iostream>
11 #include <fstream>
12 #include <sstream>
13
14 #include <errno.h>
15 #include <string.h>
16 #include <sys/stat.h>
17 #include <stdbool.h>
18
19 #include "log.h"
20 #include "FileUtil.hh"
21 #include "DeviceConfig.hh"
22
23 using namespace std;
24 using namespace plp;
25
26 template <class NumberDataType>
27 bool string_to_number(NumberDataType& result,
28                  const std::string& string_param,
29                  std::ios_base& (*format)(std::ios_base&))
30 {
31         std::istringstream iss(string_param);
32         return !(iss >> format >> result).fail();
33 }
34
35 FileUtil::FileUtil() {
36 }
37
38 FileUtil::~FileUtil() {
39 }
40
41 /*
42  * Parses directory path from the full filename and
43  * returns it's copy.
44  */
45 string FileUtil::parse_directory_path(const char *file_name_with_path) {
46         char    *p;
47         size_t  b_count;
48         size_t  f_size;
49         char    *ret;
50         string ret_val;
51
52         ret     = NULL;
53         if (file_name_with_path != NULL) {
54                 f_size  = 0;
55                 b_count = strlen(file_name_with_path);
56                 for (p = &((char *)file_name_with_path)[b_count]; p != (char *)file_name_with_path; p--) {
57                         f_size++;
58                         if ((*p == '/') ||
59                             (*p == '\\')) {
60                                 b_count = (b_count - f_size) + 1;
61                                 ret     = strndup(file_name_with_path, b_count);
62                                 //log_debug("path ret_val: %s\n", ret);
63                                 break;
64                         }
65                 }
66         }
67         if (ret != NULL) {
68                 ret_val = ret;
69                 free(ret);
70         }
71         return ret_val;
72 }
73
74 bool FileUtil::mkdirs(const char *path) {
75         bool    ret_val;
76         char    *p;
77         int     err_flg;
78
79         ret_val = true;
80         if (path != NULL) {
81                 if (access(path, F_OK) != 0) {
82                         // path does not exist, need to create it
83                         // go through each directory one by one and create them if they do not yet exist
84                         for (p = (char *)path; *p; p++) {
85                             if ((p != path) &&
86                                 ((*p == '/') ||
87                                  (*p == '\\'))) {
88                                         *p = '\0';
89                                         // if dir does not exist, create it
90                                         if (access(path, F_OK) != 0) {
91                                                 //log_debug("trying to create directory: %s\n", path);
92                                                 err_flg = mkdir(path, S_IRWXU);
93                                                 if (err_flg != 0) {
94                                                         log_error("Could not create directory: %s\n", path);
95                                                         ret_val = false;
96                                                         break;
97                                                 }
98                                         }
99                                         *p = '/';
100                                 }
101                         }
102                         if (ret_val == true) {
103                                 // if dir does not exist, create it
104                                 if (access(path, F_OK) != 0) {
105                                         //log_debug("trying to create directory: %s\n", path);
106                                         err_flg = mkdir(path, S_IRWXU);
107                                         if (err_flg != 0) {
108                                                 log_error("Could not create directory: %s\n", path);
109                                                 ret_val = false;
110                                         }
111                                 }
112                         }
113                 }
114                 else {
115                         ret_val = true;
116                 }
117         }
118         else {
119                 ret_val = false;
120                 log_error("Could not create NULL directory\n");
121         }
122         return ret_val;
123 }
124
125 bool FileUtil::file_exist(const char *file_name_with_path,
126                         bool writable) {
127         bool ret_val;
128         int acl_mode;
129
130         ret_val = false;
131         if (writable == true) {
132                 acl_mode        = W_OK;
133         }
134         else {
135                 acl_mode        = R_OK;
136         }
137         if (file_name_with_path != NULL) {
138                 if (access(file_name_with_path, acl_mode) == 0) {
139                         ret_val = true;
140                 }
141         }
142         return ret_val;
143 }
144
145 bool FileUtil::dir_exist(const char *dir_name_with_path,
146                         bool writable) {
147         bool ret_val;
148         struct stat st;
149         bool is_dir;
150
151         ret_val = false;
152         if (stat(dir_name_with_path, &st) == 0) {
153                 is_dir = S_ISDIR(st.st_mode);
154                 if (is_dir == true) {
155                         if (writable == false) {
156                                 // check only the read permission
157                                 ret_val = ((st.st_mode) & S_IRUSR);
158
159                         }
160                         else {
161                                 // check also the write permission
162                                 ret_val = ((st.st_mode) & S_IWUSR);
163                         }
164 /*
165                         int acl_mode;
166                         if (writable == true) {
167                                 acl_mode        = W_OK;
168                         }
169                         else {
170                                 acl_mode        = R_OK;
171                         }
172                         if (dir_name_with_path != NULL) {
173                                 if (access(dir_name_with_path, acl_mode) == 0) {
174                                 }
175                         }
176 */
177                 }
178         }
179         return ret_val;
180 }
181
182 bool FileUtil::mkfile(const char *file_name_with_path, bool writable) {
183         bool ret_val;
184         string path_name;
185         const char *acl;
186         int acl_mode;
187         FILE *fp;
188         bool succ_bool;
189
190         ret_val = false;
191         acl     = "a";
192         if (writable == true) {
193                 acl_mode        = W_OK;
194         }
195         else {
196                 acl_mode        = R_OK;
197         }
198         if (file_name_with_path != NULL) {
199                 if (access(file_name_with_path, F_OK) != 0) {
200                         // file does not exist, create it
201                         path_name       = parse_directory_path(file_name_with_path);
202                         succ_bool = true;
203                         if (access(path_name.c_str(), F_OK) != 0) {
204                                 // path to file does not exist, create it
205                                 succ_bool       = mkdirs(path_name.c_str());
206                         }
207                         if (succ_bool == true) {
208                                 // create file with read or write acl rights
209                                 fp      = fopen(file_name_with_path, acl);
210                                 if (fp != NULL) {
211                                         ret_val = true;
212                                         fclose(fp);
213                                 }
214                         }
215                 }
216                 else {
217                         // file already exist, check access rights and change if needed
218                         ret_val = true;
219                         if (access(file_name_with_path, acl_mode) != 0) {
220                                 // file does not have specified acl righs, try to grant them
221                                 fp      = fopen(file_name_with_path, acl);
222                                 if (fp != NULL) {
223                                         ret_val = true;
224                                         fclose(fp);
225                                 }
226                         }
227                 }
228         }
229         return ret_val;
230
231 /*
232                 path_name = parse_directory_path(file_name_with_path)
233                 if (cfg_dir.empty() == false) {
234                         if (access(path_name.c_str(), F_OK) != 0) {
235                                 // config dir does not exist, create it
236                                 FileUtil::mkdirs(cfg_dir.c_str());
237                         }
238                         if (access(cfg_dir.c_str(), R_OK) != 0) {
239                                 // config dir does not have read access, add it
240                                 fp      = fopen(cfg_dir.c_str(), "r+");
241                                 if (fp != NULL)
242                                         fclose(fp);
243                         }
244                         fname_full      = get_config_file_name();
245                         if (access(fname_full.c_str(), F_OK) != 0) {
246                                 // config file does not exist, create empty one
247                                 fp      = fopen(fname_full.c_str(), "w+");
248                                 if (fp != NULL)
249                                         fclose(fp);
250                         }
251                         if (access(fname_full.c_str(), R_OK) != 0) {
252                                 // config file does not have read access, add it
253                                 fp      = fopen(fname_full.c_str(), "r+");
254                                 if (fp != NULL)
255                                         fclose(fp);
256                         }
257                         if (access(fname_full.c_str(), R_OK) == 0) {
258
259                         }
260 */
261 }
262
263 std::ofstream *FileUtil::open_for_writing(const char *f_path) {
264         string          path_name;
265         size_t          b_count;
266         ofstream        *ret_val;
267         bool            b_flg;
268
269         ret_val = NULL;
270         b_flg   = true;
271         if (f_path != NULL) {
272                 b_count = strlen(f_path);
273                 if ((f_path[b_count - 1] != '/') &&
274                     (f_path[b_count - 1] != '\\')) {
275                         ret_val = new ofstream();
276                         ret_val->open(f_path, ios::app);
277                         if (ret_val->is_open() == false) {
278                                 path_name       = parse_directory_path(f_path);
279                                 if (path_name.empty() == false) {
280                                         b_flg   = mkdirs(path_name.c_str());
281                                 }
282                                 if (b_flg == true) {
283                                         ret_val->open(f_path, ios::app);
284                                 }
285                         }
286                 }
287                 else {
288                         log_error("Could not open file, invalid file name. (%s)\n", f_path);
289                 }
290         }
291         else {
292                 log_error("Could not open file, invalid file name. (= NULL)\n");
293         }
294         return ret_val;
295 }
296
297 string FileUtil::concat_paths(string path_start, string path_end) {
298         return concat_paths(path_start.c_str(), path_end.c_str());
299 }
300
301 string FileUtil::concat_paths(const char *path_start, const char *path_end) {
302         string  ret_val;
303         string  end_str;
304         int     pos;
305         int     b_count;
306
307         if (path_start != NULL) {
308                 ret_val = path_start;
309                 if (path_end != NULL) {
310                         end_str = path_end;
311                         b_count = ret_val.length();
312                         pos     = ret_val.find_last_of("/");
313                         if (pos == (b_count -1)) {
314                                 ret_val.append(end_str);
315                         }
316                         else {
317                                 pos     = end_str.find_first_of("/");
318                                 if (pos == 0) {
319                                         ret_val.append(end_str);
320                                 }
321                                 else {
322                                         ret_val.append("/");
323                                         ret_val.append(end_str);
324                                 }
325                         }
326                 }
327         }
328         else {
329                 if (path_end != NULL) {
330                         ret_val = path_end;
331                 }
332         }
333         return ret_val;
334 }
335
336 bool FileUtil::is_subdirectory(const char *path, dirent *direntry) {
337         bool            ret_val;
338         struct stat     stat_info;
339         string          fname;
340
341         ret_val = false;
342         if (direntry != NULL) {
343                 if ((strcmp(direntry->d_name, ".") == 0) ||
344                     (strcmp(direntry->d_name, "..") == 0)) {
345                         ret_val = false;
346                 }
347                 else {
348                         fname   = concat_paths(path, direntry->d_name);
349                         stat(fname.c_str(), &stat_info);
350                         ret_val = S_ISDIR(stat_info.st_mode);
351                         //log_debug("stat for: %s: %d\n", fname.c_str(), ret_val);
352                 }
353         }
354         return ret_val;
355 }
356
357 bool FileUtil::is_datafile(const char *path, dirent *direntry) {
358         bool            ret_val;
359         struct stat     stat_info;
360         string          name;
361         int             pos;
362         string          fname;
363
364         ret_val = false;
365         if (direntry != NULL) {
366                 name    = direntry->d_name;
367                 pos     = name.find(DATAFILE_SUFFIX);
368                 if (pos > 0) {
369                         fname   = concat_paths(path, direntry->d_name);
370                         stat(fname.c_str(), &stat_info);
371                         ret_val = S_ISREG(stat_info.st_mode);
372                 }
373         }
374         return ret_val;
375 }
376
377 /**
378  * get sub-directories sorted in alphabetical order.
379  */
380 vector<string> FileUtil::get_subdirectories(const string& path) {
381         dirent          *direntry;
382         DIR             *dir;
383         bool            bool_flg;
384         vector<string>  ret_val;
385
386         //log_debug("scanning path: %s\n", path.c_str());
387         errno   = 0;
388         if (path.empty() == false) {
389                 dir     = opendir(path.c_str());
390                 if (dir) {
391                         while (true) {
392                                 errno           = 0;
393                                 direntry        = readdir(dir);
394                                 if (direntry != NULL) {
395                                         bool_flg        = is_subdirectory(path.c_str(), direntry);
396                                         if (bool_flg == true) {
397                                                 ret_val.push_back(string(direntry->d_name));
398                                                 //log_debug("added dir: %s\n", direntry->d_name);
399                                         }
400                                 }
401                                 else {
402                                         break;
403                                 }
404                         }
405                         closedir(dir);
406                         sort(ret_val.begin(), ret_val.end());
407                 }
408         }
409         return ret_val;
410 }
411
412 /**
413  * get sub-directories sorted in alphabetical order.
414  */
415 vector<string> FileUtil::get_data_files(const string& path) {
416         dirent          *direntry;
417         DIR             *dir;
418         vector<string>  ret_val;
419
420         errno   = 0;
421         if (path.empty() == false) {
422                 dir     = opendir(path.c_str());
423                 if (dir) {
424                         while (true) {
425                                 errno           = 0;
426                                 direntry        = readdir(dir);
427                                 if (direntry != NULL) {
428                                         if (is_datafile(path.c_str(), direntry) == true) {
429                                                 ret_val.push_back(string(direntry->d_name));
430                                         }
431                                 }
432                                 else {
433                                         break;
434                                 }
435                         }
436                         closedir(dir);
437                         sort(ret_val.begin(), ret_val.end());
438                 }
439         }
440         return ret_val;
441 }