]> pilppa.org Git - libplp.git/blob - src/FileUtil.cc
api fixes and cleanups
[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, bool writable) {
126         bool ret_val;
127         int acl_mode;
128
129         ret_val = false;
130         if (writable == true) {
131                 acl_mode        = W_OK;
132         }
133         else {
134                 acl_mode        = R_OK;
135         }
136         if (file_name_with_path != NULL) {
137                 if (access(file_name_with_path, acl_mode) == 0) {
138                         ret_val = true;
139                 }
140         }
141         return ret_val;
142 }
143
144 bool FileUtil::mkfile(const char *file_name_with_path, bool writable) {
145         bool ret_val;
146         string path_name;
147         const char *acl;
148         int acl_mode;
149         FILE *fp;
150         bool succ_bool;
151
152         ret_val = false;
153         acl     = "a";
154         if (writable == true) {
155                 acl_mode        = W_OK;
156         }
157         else {
158                 acl_mode        = R_OK;
159         }
160         if (file_name_with_path != NULL) {
161                 if (access(file_name_with_path, F_OK) != 0) {
162                         // file does not exist, create it
163                         path_name       = parse_directory_path(file_name_with_path);
164                         succ_bool = true;
165                         if (access(path_name.c_str(), F_OK) != 0) {
166                                 // path to file does not exist, create it
167                                 succ_bool       = mkdirs(path_name.c_str());
168                         }
169                         if (succ_bool == true) {
170                                 // create file with read or write acl rights
171                                 fp      = fopen(file_name_with_path, acl);
172                                 if (fp != NULL) {
173                                         ret_val = true;
174                                         fclose(fp);
175                                 }
176                         }
177                 }
178                 else {
179                         // file already exist, check access rights and change if needed
180                         ret_val = true;
181                         if (access(file_name_with_path, acl_mode) != 0) {
182                                 // file does not have specified acl righs, try to grant them
183                                 fp      = fopen(file_name_with_path, acl);
184                                 if (fp != NULL) {
185                                         ret_val = true;
186                                         fclose(fp);
187                                 }
188                         }
189                 }
190         }
191         return ret_val;
192
193 /*
194                 path_name = parse_directory_path(file_name_with_path)
195                 if (cfg_dir.empty() == false) {
196                         if (access(path_name.c_str(), F_OK) != 0) {
197                                 // config dir does not exist, create it
198                                 FileUtil::mkdirs(cfg_dir.c_str());
199                         }
200                         if (access(cfg_dir.c_str(), R_OK) != 0) {
201                                 // config dir does not have read access, add it
202                                 fp      = fopen(cfg_dir.c_str(), "r+");
203                                 if (fp != NULL)
204                                         fclose(fp);
205                         }
206                         fname_full      = get_config_file_name();
207                         if (access(fname_full.c_str(), F_OK) != 0) {
208                                 // config file does not exist, create empty one
209                                 fp      = fopen(fname_full.c_str(), "w+");
210                                 if (fp != NULL)
211                                         fclose(fp);
212                         }
213                         if (access(fname_full.c_str(), R_OK) != 0) {
214                                 // config file does not have read access, add it
215                                 fp      = fopen(fname_full.c_str(), "r+");
216                                 if (fp != NULL)
217                                         fclose(fp);
218                         }
219                         if (access(fname_full.c_str(), R_OK) == 0) {
220
221                         }
222 */
223 }
224
225 std::ofstream *FileUtil::open_for_writing(const char *f_path) {
226         string          path_name;
227         size_t          b_count;
228         ofstream        *ret_val;
229         bool            b_flg;
230
231         ret_val = NULL;
232         b_flg   = true;
233         if (f_path != NULL) {
234                 b_count = strlen(f_path);
235                 if ((f_path[b_count - 1] != '/') &&
236                     (f_path[b_count - 1] != '\\')) {
237                         ret_val = new ofstream();
238                         ret_val->open(f_path, ios::app);
239                         if (ret_val->is_open() == false) {
240                                 path_name       = parse_directory_path(f_path);
241                                 if (path_name.empty() == false) {
242                                         b_flg   = mkdirs(path_name.c_str());
243                                 }
244                                 if (b_flg == true) {
245                                         ret_val->open(f_path, ios::app);
246                                 }
247                         }
248                 }
249                 else {
250                         log_error("Could not open file, invalid file name. (%s)\n", f_path);
251                 }
252         }
253         else {
254                 log_error("Could not open file, invalid file name. (= NULL)\n");
255         }
256         return ret_val;
257 }
258
259 string FileUtil::concat_paths(string path_start, string path_end) {
260         return concat_paths(path_start.c_str(), path_end.c_str());
261 }
262
263 string FileUtil::concat_paths(const char *path_start, const char *path_end) {
264         string  ret_val;
265         string  end_str;
266         int     pos;
267         int     b_count;
268
269         if (path_start != NULL) {
270                 ret_val = path_start;
271                 if (path_end != NULL) {
272                         end_str = path_end;
273                         b_count = ret_val.length();
274                         pos     = ret_val.find_last_of("/");
275                         if (pos == (b_count -1)) {
276                                 ret_val.append(end_str);
277                         }
278                         else {
279                                 pos     = end_str.find_first_of("/");
280                                 if (pos == 0) {
281                                         ret_val.append(end_str);
282                                 }
283                                 else {
284                                         ret_val.append("/");
285                                         ret_val.append(end_str);
286                                 }
287                         }
288                 }
289         }
290         else {
291                 if (path_end != NULL) {
292                         ret_val = path_end;
293                 }
294         }
295         return ret_val;
296 }
297
298 bool FileUtil::is_subdirectory(const char *path, dirent *direntry) {
299         bool            ret_val;
300         struct stat     stat_info;
301         string          fname;
302
303         ret_val = false;
304         if (direntry != NULL) {
305                 if ((strcmp(direntry->d_name, ".") == 0) ||
306                     (strcmp(direntry->d_name, "..") == 0)) {
307                         ret_val = false;
308                 }
309                 else {
310                         fname   = concat_paths(path, direntry->d_name);
311                         stat(fname.c_str(), &stat_info);
312                         ret_val = S_ISDIR(stat_info.st_mode);
313                         //log_debug("stat for: %s: %d\n", fname.c_str(), ret_val);
314                 }
315         }
316         return ret_val;
317 }
318
319 bool FileUtil::is_datafile(const char *path, dirent *direntry) {
320         bool            ret_val;
321         struct stat     stat_info;
322         string          name;
323         int             pos;
324         string          fname;
325
326         ret_val = false;
327         if (direntry != NULL) {
328                 name    = direntry->d_name;
329                 pos     = name.find(DATAFILE_SUFFIX);
330                 if (pos > 0) {
331                         fname   = concat_paths(path, direntry->d_name);
332                         stat(fname.c_str(), &stat_info);
333                         ret_val = S_ISREG(stat_info.st_mode);
334                 }
335         }
336         return ret_val;
337 }
338
339 /**
340  * get sub-directories sorted in alphabetical order.
341  */
342 vector<string> FileUtil::get_subdirectories(const string& path) {
343         dirent          *direntry;
344         DIR             *dir;
345         bool            bool_flg;
346         vector<string>  ret_val;
347
348         //log_debug("scanning path: %s\n", path.c_str());
349         errno   = 0;
350         if (path.empty() == false) {
351                 dir     = opendir(path.c_str());
352                 if (dir) {
353                         while (true) {
354                                 errno           = 0;
355                                 direntry        = readdir(dir);
356                                 if (direntry != NULL) {
357                                         bool_flg        = is_subdirectory(path.c_str(), direntry);
358                                         if (bool_flg == true) {
359                                                 ret_val.push_back(string(direntry->d_name));
360                                                 //log_debug("added dir: %s\n", direntry->d_name);
361                                         }
362                                 }
363                                 else {
364                                         break;
365                                 }
366                         }
367                         closedir(dir);
368                         sort(ret_val.begin(), ret_val.end());
369                 }
370         }
371         return ret_val;
372 }
373
374 /**
375  * get sub-directories sorted in alphabetical order.
376  */
377 vector<string> FileUtil::get_data_files(const string& path) {
378         dirent          *direntry;
379         DIR             *dir;
380         vector<string>  ret_val;
381
382         errno   = 0;
383         if (path.empty() == false) {
384                 dir     = opendir(path.c_str());
385                 if (dir) {
386                         while (true) {
387                                 errno           = 0;
388                                 direntry        = readdir(dir);
389                                 if (direntry != NULL) {
390                                         if (is_datafile(path.c_str(), direntry) == true) {
391                                                 ret_val.push_back(string(direntry->d_name));
392                                         }
393                                 }
394                                 else {
395                                         break;
396                                 }
397                         }
398                         closedir(dir);
399                         sort(ret_val.begin(), ret_val.end());
400                 }
401         }
402         return ret_val;
403 }