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