source: sources/src/toolsFilesystem.cc @ 1464:3f6711617be1

Revision 1464:3f6711617be1, 34.9 KB checked in by niam, 22 months ago (diff)

{issue #58[resolved]} support for non-c++ exceptions

Line 
1/***************************************************************************
2 *            toolsFilesystem.cc
3 *
4 *  Wed Oct 8 2005
5 *  Copyright  2005  Dmytro Milinevskyy
6 *  milinevskyy@gmail.com
7 ****************************************************************************/
8
9/*
10 *  This program is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU Lesser General Public License version 2.1 as published by
12 *  the Free Software Foundation;
13 *
14 *  This program is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU Library General Public License for more details.
18 *
19 *  You should have received a copy of the GNU Lesser General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24/**
25 * vim indentation settings
26 * set tabstop=4
27 * set shiftwidth=4
28 */
29
30#include <libdodo/directives.h>
31
32#include <string.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <fcntl.h>
36#include <dirent.h>
37#include <utime.h>
38#include <time.h>
39#include <libgen.h>
40#include <unistd.h>
41#include <errno.h>
42#include <stdio.h>
43
44#include <libdodo/toolsFilesystem.h>
45#include <libdodo/toolsFilesystemEx.h>
46#include <libdodo/types.h>
47
48using namespace dodo::tools;
49
50void
51filesystem::unlink(const dodo::string &path,
52                   bool             force)
53{
54    int status(0);
55    struct stat st;
56
57    if (::lstat(path.data(), &st) == -1)
58        if (errno != ENOENT || !force)
59            dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_UNLINK, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
60
61    if (S_ISDIR(st.st_mode))
62        status = ::rmdir(path.data());
63    else
64        status = ::unlink(path.data());
65
66    if (status == -1)
67        if (errno != ENOENT || !force)
68            dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_UNLINK, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
69}
70
71//-------------------------------------------------------------------
72
73void
74filesystem::rename(const dodo::string &oldPath,
75                   const dodo::string &newPath)
76{
77    if (::rename(oldPath.data(), newPath.data()) == -1)
78        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_RENAME, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, oldPath + "->" + newPath);
79}
80
81//-------------------------------------------------------------------
82
83void
84filesystem::symlink(const dodo::string &oldPath,
85                    const dodo::string &newPath,
86                    bool             force)
87{
88    if (force) {
89        struct stat st;
90        if (::lstat(newPath.data(), &st) != -1) {
91            if (!S_ISLNK(st.st_mode))
92                dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_SYMLINK, exception::ERRNO_LIBDODO, FILESYSTEMEX_WRONGFILENAME, TOOLSFILESYSTEMEX_WRONGFILENAME_STR, __LINE__, __FILE__, newPath);
93            else if (::unlink(newPath.data()) == -1)
94                dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_SYMLINK, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, newPath);
95        }
96    }
97
98    if (::symlink(oldPath.data(), newPath.data()) == -1)
99        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_SYMLINK, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, oldPath + "->" + newPath);
100}
101
102//-------------------------------------------------------------------
103
104void
105filesystem::link(const dodo::string &oldPath,
106                 const dodo::string &newPath)
107{
108    if  (::link(oldPath.data(), newPath.data()) == -1)
109        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_LINK, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, oldPath + "->" + newPath);
110}
111
112//-------------------------------------------------------------------
113
114void
115filesystem::chown(const dodo::string &path,
116                  int              uid)
117{
118    if (::chown(path.data(), uid, (unsigned int)-1) == -1)
119        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_CHOWN, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
120}
121
122//-------------------------------------------------------------------
123
124void
125filesystem::chgrp(const dodo::string &path,
126                  int              gid)
127{
128    if (::chown(path.data(), (unsigned int)-1, gid) == -1)
129        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_CHGRP, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
130}
131
132//-------------------------------------------------------------------
133
134int
135filesystem::userOwner(const dodo::string &path)
136{
137    struct stat st;
138    if (::lstat(path.data(), &st) == -1)
139        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_USEROWNER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
140
141    return st.st_uid;
142}
143
144//-------------------------------------------------------------------
145
146int
147filesystem::groupOwner(const dodo::string &path)
148{
149    struct stat st;
150    if (::lstat(path.data(), &st) == -1)
151        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_GROUPOWNER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
152
153    return st.st_gid;
154}
155
156//-------------------------------------------------------------------
157
158void
159filesystem::touch(const dodo::string &path,
160                  int              a_time)
161{
162    if (a_time == 1)
163        a_time = time(NULL);
164
165    utimbuf temp = {
166        a_time, a_time
167    };
168
169    if (::utime(path.data(), &temp) == -1)
170        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_TOUCH, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
171}
172
173//-------------------------------------------------------------------
174
175void
176filesystem::mkfifo(const dodo::string &path,
177                   int              permissions)
178{
179    if (::mkfifo(path.data(), toRealPermission(permissions)) == -1)
180        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_MKFIFO, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
181}
182
183//-------------------------------------------------------------------
184
185void
186filesystem::mkdir(const dodo::string &path,
187                  int              permissions)
188{
189    if (::mkdir(path.data(), toRealPermission(permissions)) == -1) {
190        if (errno == EEXIST) {
191            struct stat st;
192            if (::lstat(path.data(), &st) == -1)
193                dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_MKDIR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
194
195            if (!S_ISDIR(st.st_mode))
196                dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_MKDIR, exception::ERRNO_LIBDODO, FILESYSTEMEX_NOTADIR, TOOLSFILESYSTEMEX_NOTADIR_STR, __LINE__, __FILE__, path);
197        } else {
198            mkdir(dirname(path), permissions);
199
200            if (::mkdir(path.data(), toRealPermission(permissions)) == -1) {
201                if (errno == EEXIST) {
202                    struct stat st;
203                    if (::lstat(path.data(), &st) == -1)
204                        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_MKDIR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
205
206                    if (!S_ISDIR(st.st_mode))
207                        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_MKDIR, exception::ERRNO_LIBDODO, FILESYSTEMEX_NOTADIR, TOOLSFILESYSTEMEX_NOTADIR_STR, __LINE__, __FILE__, path);
208                }
209            }
210        }
211    }
212}
213
214//-------------------------------------------------------------------
215
216void
217filesystem::chmod(const dodo::string &path,
218                  int              permissions)
219{
220    if (::chmod(path.data(), toRealPermission(permissions)) == -1)
221        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_CHMOD, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
222}
223
224//-------------------------------------------------------------------
225
226int
227filesystem::toRealPermission(int permission)
228{
229    int mode(0);
230
231    if (isSetFlag(permission, PERMISSION_OWNER_READ_ACCESS))
232        mode |= S_IRUSR;
233    if (isSetFlag(permission, PERMISSION_GROUP_READ_ACCESS))
234        mode |= S_IRGRP;
235    if (isSetFlag(permission, PERMISSION_OTHER_READ_ACCESS))
236        mode |= S_IROTH;
237
238    if (isSetFlag(permission, PERMISSION_OWNER_WRITE_ACCESS))
239        mode |= S_IWUSR;
240    if (isSetFlag(permission, PERMISSION_GROUP_WRITE_ACCESS))
241        mode |= S_IWGRP;
242    if (isSetFlag(permission, PERMISSION_OTHER_WRITE_ACCESS))
243        mode |= S_IWOTH;
244
245    if (isSetFlag(permission, PERMISSION_OWNER_EXECUTE_ACCESS))
246        mode |= S_IXUSR;
247    if (isSetFlag(permission, PERMISSION_GROUP_EXECUTE_ACCESS))
248        mode |= S_IXGRP;
249    if (isSetFlag(permission, PERMISSION_OTHER_EXECUTE_ACCESS))
250        mode |= S_IXOTH;
251
252    if (isSetFlag(permission, PERMISSION_STICKY_ACCESS))
253        mode |= S_ISVTX;
254
255    if (isSetFlag(permission, PERMISSION_SUID_ACCESS))
256        mode |= S_ISUID;
257    if (isSetFlag(permission, PERMISSION_SGID_ACCESS))
258        mode |= S_ISGID;
259
260    return mode;
261}
262
263//-------------------------------------------------------------------
264
265void
266filesystem::rm(const dodo::string &path,
267               bool             force)
268{
269    struct stat st;
270    if (::lstat(path.data(), &st) == -1) {
271        if (errno != ENOENT || !force)
272            dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_RM, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
273        else
274            return ;
275    }
276
277    if (!S_ISDIR(st.st_mode)) {
278        if (::unlink(path.data()) == -1)
279            if (errno != ENOENT || !force)
280                dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_RM, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
281    } else {
282        dodo::string attached;
283
284        DIR *directory = opendir(path.data());
285
286        if (directory == NULL) {
287            if (errno != ENOENT || !force)
288                dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_RM, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
289        } else {
290            dirent *dd;
291
292            while ((dd = readdir(directory)) != NULL) {
293                if ((strcmp(dd->d_name, ".") == 0) || (strcmp(dd->d_name, "..") == 0))
294                    continue;
295
296                attached = dodo::string(path + "/" + dd->d_name);
297
298                if (::lstat(attached.data(), &st) == -1)
299                    if (errno != ENOENT || !force)
300                        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_RM, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
301
302                if (S_ISDIR(st.st_mode))
303                    filesystem::rm(attached.data());
304                else if (::unlink(attached.data()) == -1)
305                    if (errno != ENOENT || !force)
306                        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_RM, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
307            }
308
309            if (closedir(directory) == -1)
310                dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_RM, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
311
312            if (::rmdir(path.data()) == -1)
313                if (errno != ENOENT || !force)
314                    dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_RM, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
315        }
316    }
317}
318
319//-------------------------------------------------------------------
320
321int
322filesystem::permissions(const dodo::string &path)
323{
324    struct stat st;
325    if (::lstat(path.data(), &st) == -1)
326        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_PERMISSIONS, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
327
328    int mode(PERMISSION_NONE);
329
330    if (isSetFlag(st.st_mode, S_IRUSR))
331        mode |= PERMISSION_OWNER_READ_ACCESS;
332    if (isSetFlag(st.st_mode, S_IRGRP))
333        mode |= PERMISSION_GROUP_READ_ACCESS;
334    if (isSetFlag(st.st_mode, S_IROTH))
335        mode |= PERMISSION_OTHER_READ_ACCESS;
336
337    if (isSetFlag(st.st_mode, S_IWUSR))
338        mode |= PERMISSION_OWNER_WRITE_ACCESS;
339    if (isSetFlag(st.st_mode, S_IWGRP))
340        mode |= PERMISSION_GROUP_WRITE_ACCESS;
341    if (isSetFlag(st.st_mode, S_IWOTH))
342        mode |= PERMISSION_OTHER_WRITE_ACCESS;
343
344    if (isSetFlag(st.st_mode, S_ISVTX))
345        mode |= PERMISSION_STICKY_ACCESS;
346
347    if (isSetFlag(st.st_mode, S_IXUSR))
348        mode |= PERMISSION_OWNER_EXECUTE_ACCESS;
349    if (isSetFlag(st.st_mode, S_IXGRP))
350        mode |= PERMISSION_GROUP_EXECUTE_ACCESS;
351    if (isSetFlag(st.st_mode, S_IXOTH))
352        mode |= PERMISSION_OTHER_EXECUTE_ACCESS;
353
354    if (isSetFlag(st.st_mode, S_ISUID))
355        mode |= PERMISSION_SUID_ACCESS;
356    if (isSetFlag(st.st_mode, S_ISGID))
357        mode |= PERMISSION_SGID_ACCESS;
358
359    return mode;
360}
361
362//-------------------------------------------------------------------
363
364int
365filesystem::fileType(const dodo::string &path)
366{
367    struct stat st;
368    if (::lstat(path.data(), &st) == -1)
369        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_FILETYPE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
370
371    st.st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX);
372
373    switch (st.st_mode) {
374        case S_IFREG:
375
376            return FILE_REGULAR_FILE;
377
378        case S_IFDIR:
379
380            return FILE_DIRECTORY;
381
382        case S_IFLNK:
383
384            return FILE_SYMBOLIC_LINK;
385
386        case S_IFSOCK:
387
388            return FILE_LOCAL_SOCKET;
389
390        case S_IFBLK:
391
392            return FILE_BLOCK_DEVICE;
393
394        case S_IFCHR:
395
396            return FILE_CHARACTER_DEVICE;
397
398        case S_IFIFO:
399
400            return FILE_FIFO;
401
402        default:
403
404            return -1;
405    }
406}
407
408//-------------------------------------------------------------------
409
410long
411filesystem::size(const dodo::string &path)
412{
413    struct stat st;
414    if (::lstat(path.data(), &st) == -1)
415        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_SIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
416
417    return st.st_size;
418}
419
420//-------------------------------------------------------------------
421
422long
423filesystem::accessTime(const dodo::string &path)
424{
425    struct stat st;
426    if (::lstat(path.data(), &st) == -1)
427        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_ACCTIME, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
428
429    return st.st_atime;
430}
431
432//-------------------------------------------------------------------
433
434long
435filesystem::modificationTime(const dodo::string &path)
436{
437    struct stat st;
438    if (::lstat(path.data(), &st) == -1)
439        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_MODTIME, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
440
441    return st.st_mtime;
442}
443
444//-------------------------------------------------------------------
445
446filesystem::__file__
447filesystem::file(const dodo::string &path)
448{
449    __file__ file;
450
451    struct stat st;
452    if (::lstat(path.data(), &st) == -1)
453        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_FILEINFO, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
454
455    file.name = dodo::string(::basename((char *)path.data()));
456    file.type = filesystem::fileType(path);
457    file.perm = filesystem::permissions(path);
458    file.accTime = filesystem::accessTime(path);
459    file.modTime = filesystem::modificationTime(path);
460    file.size = filesystem::size(path);
461    file.uid = filesystem::userOwner(path);
462    file.gid = filesystem::groupOwner(path);
463
464    return file;
465}
466
467//-------------------------------------------------------------------
468
469dodoArray<filesystem::__file__>
470filesystem::dir(const dodo::string &path)
471{
472    dodoArray<__file__> dir;
473    struct stat st;
474    if (::lstat(path.data(), &st) == -1)
475        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_DIRINFO, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
476
477    if (!S_ISDIR(st.st_mode))
478        return dir;
479
480    DIR *directory = opendir(path.data());
481
482    if (directory == NULL)
483        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_DIRINFO, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
484
485    dirent *dd;
486    dodo::string attached;
487
488    while ((dd = readdir(directory)) != NULL) {
489        if ((strcmp(dd->d_name, ".") == 0) || (strcmp(dd->d_name, "..") == 0))
490            continue;
491        attached = dodo::string(path + "/" + dd->d_name);
492        dir.push_back(filesystem::file(attached));
493    }
494
495    return dir;
496}
497
498//-------------------------------------------------------------------
499
500dodo::string
501filesystem::followSymlink(const dodo::string &path)
502{
503    struct stat st;
504    if (::lstat(path.data(), &st) == -1)
505        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_FOLLOWSYMLINK, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
506
507    char buffer[PATH_MAXLEN + 1];
508
509    if (!S_ISLNK(st.st_mode))
510        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_SYMLINK, exception::ERRNO_LIBDODO, FILESYSTEMEX_WRONGFILENAME, TOOLSFILESYSTEMEX_WRONGFILENAME_STR, __LINE__, __FILE__, path);
511
512    int count = 0;
513
514    if ((count = ::readlink(path.data(), buffer, PATH_MAXLEN)) == -1)
515        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_FOLLOWSYMLINK, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
516
517    return buffer;
518}
519
520//-------------------------------------------------------------------
521
522dodo::string
523filesystem::fileContents(const dodo::string &path)
524{
525    struct stat st;
526    if (::lstat(path.data(), &st) == -1)
527        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_FILECONTENTS, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
528
529    if (!S_ISREG(st.st_mode))
530        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_FILECONTENTS, exception::ERRNO_LIBDODO, FILESYSTEMEX_WRONGFILENAME, TOOLSFILESYSTEMEX_WRONGFILENAME_STR, __LINE__, __FILE__, path);
531
532    FILE *file = fopen(path.data(), "r");
533    if (file == NULL)
534        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_FILECONTENTS, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
535
536    char buffer[IO_BLOCKSIZE];
537
538    long iter = st.st_size / IO_BLOCKSIZE, rest = st.st_size % IO_BLOCKSIZE;
539    dodo::string retS = "";
540
541    int i(0);
542    for (; i < iter; ++i) {
543        if (fread(buffer, IO_BLOCKSIZE, 1, file) == 0) {
544            switch (errno) {
545                case EIO:
546                case EINTR:
547                case ENOMEM:
548                case EOVERFLOW:
549                case EROFS:
550
551                    dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_FILECONTENTS, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
552            }
553        }
554
555        retS += dodo::string(buffer, IO_BLOCKSIZE);
556    }
557    if (rest > 0) {
558        if (fread(buffer, rest, 1, file) == 0) {
559            switch (errno) {
560                case EIO:
561                case EINTR:
562                case ENOMEM:
563                case EOVERFLOW:
564                case EROFS:
565
566                    dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_FILECONTENTS, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
567            }
568        }
569
570        retS += dodo::string(buffer, rest);
571    }
572
573    if (fclose(file) != 0)
574        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_FILECONTENTS, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
575
576    return retS;
577}
578
579//-------------------------------------------------------------------
580
581dodo::dodoStringArray
582filesystem::fileContentsInArray(const dodo::string &path)
583{
584    struct stat st;
585    if (::lstat(path.data(), &st) == -1)
586        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_FILECONTENTSARR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
587
588    if (!S_ISREG(st.st_mode))
589        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_FILECONTENTSARR, exception::ERRNO_LIBDODO, FILESYSTEMEX_WRONGFILENAME, TOOLSFILESYSTEMEX_WRONGFILENAME_STR, __LINE__, __FILE__, path);
590
591    FILE *file = fopen(path.data(), "r");
592    if (file == NULL)
593        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_FILECONTENTSARR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
594
595    char buffer[LINE_MAXLEN];
596    dodoStringArray arr;
597
598    while (fgets(buffer, LINE_MAXLEN, file) != NULL)
599        arr.push_back(buffer);
600
601    if (fclose(file) != 0)
602        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_FILECONTENTSARR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
603
604    return arr;
605}
606
607//-------------------------------------------------------------------
608
609#ifdef basename
610inline char *
611original_basename(char *path)
612{
613    return ::basename(path);
614}
615
616#undef basename
617
618dodo::string
619filesystem::basename(const dodo::string &path)
620{
621    if (path.size() >= PATH_MAXLEN)
622        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_BASENAME, exception::ERRNO_LIBDODO, FILESYSTEMEX_TOOLONGPATH, TOOLSFILESYSTEMEX_TOOLONGPATH_STR, __LINE__, __FILE__, path);
623
624    char temp[PATH_MAXLEN];
625
626    strcpy(temp, path.data());
627
628    return original_basename(temp);
629}
630#else
631dodo::string
632filesystem::basename(const dodo::string &path)
633{
634    if (path.size() >= PATH_MAXLEN)
635        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_BASENAME, exception::ERRNO_LIBDODO, FILESYSTEMEX_TOOLONGPATH, TOOLSFILESYSTEMEX_TOOLONGPATH_STR, __LINE__, __FILE__, path);
636
637    char temp[PATH_MAXLEN];
638
639    strcpy(temp, path.data());
640
641    return ::basename(temp);
642}
643#endif
644
645//-------------------------------------------------------------------
646
647dodo::string
648filesystem::dirname(const dodo::string &path)
649{
650    if (path.size() >= PATH_MAXLEN)
651        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_DIRNAME, exception::ERRNO_LIBDODO, FILESYSTEMEX_TOOLONGPATH, TOOLSFILESYSTEMEX_TOOLONGPATH_STR, __LINE__, __FILE__, path);
652
653    char temp[PATH_MAXLEN];
654
655    strcpy(temp, path.data());
656
657    return ::dirname(temp);
658}
659
660//-------------------------------------------------------------------
661
662void
663filesystem::copy(const dodo::string &from,
664                 const dodo::string &a_to,
665                 bool             force)
666{
667    dodo::string to = a_to;
668
669    {
670        char temp[PATH_MAXLEN];
671
672        strcpy(temp, to.data());
673        char *bname = ::basename(temp);
674        if (strcmp(bname, "..") == 0  || strcmp(bname, ".") == 0 || a_to[a_to.size() - 1] == '/')
675            to = bname + dodo::string("/") + basename((char *)from.data());
676    }
677
678    struct stat stFrom, stTo;
679
680    if (::lstat(from.data(), &stFrom) == -1)
681        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, from);
682
683    if (::lstat(to.data(), &stTo) == -1) {
684        if (errno != ENOENT)
685            dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, to);
686    } else {
687        if (force) {
688            if (!S_ISDIR(stTo.st_mode)) {
689                if (::unlink(to.data()) == -1)
690                    dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_UNLINK, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, to);
691            } else if (::rmdir(to.data()) == -1)
692                dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_UNLINK, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, to);
693        } else
694            dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_LIBDODO, FILESYSTEMEX_WRONGFILENAME, TOOLSFILESYSTEMEX_WRONGFILENAME_STR, __LINE__, __FILE__, to);
695    }
696
697    if (!S_ISREG(stFrom.st_mode)) {
698        if (S_ISDIR(stFrom.st_mode)) {
699            if (::mkdir(to.data(), stFrom.st_mode) == 1)
700                dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, to);
701        } else if (S_ISLNK(stFrom.st_mode)) {
702            char buffer[PATH_MAXLEN];
703            int count = 0;
704
705            if ((count = ::readlink(from.data(), buffer, PATH_MAXLEN)) == -1)
706                dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, from);
707
708            buffer[count] = '\0';
709
710            if (::symlink(buffer, to.data()) == -1)
711                dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, dodo::string(buffer) + "->" + to);
712        } else if (::mknod(to.data(), stFrom.st_mode, 0) == 1)
713            dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, to);
714    } else {
715        long iter = stFrom.st_size / IO_BLOCKSIZE, rest = stFrom.st_size % IO_BLOCKSIZE;
716
717        FILE *fromFile = fopen(from.data(), "r");
718        if (fromFile == NULL)
719            dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, from);
720
721        FILE *toFile = fopen(to.data(), "w+");
722        if (toFile == NULL)
723            dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, to);
724
725        char buffer[IO_BLOCKSIZE];
726
727        int i(0);
728        for (; i < iter; ++i) {
729            if (fread(buffer, IO_BLOCKSIZE, 1, fromFile) == 0) {
730                switch (errno) {
731                    case EIO:
732                    case EINTR:
733                    case ENOMEM:
734                    case EOVERFLOW:
735                    case EROFS:
736
737                        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, from + "->" + to);
738                }
739            }
740
741            if (fwrite(buffer, IO_BLOCKSIZE, 1, toFile) == 0) {
742                switch (errno) {
743                    case EIO:
744                    case EINTR:
745                    case ENOMEM:
746                    case EOVERFLOW:
747                    case EROFS:
748
749                        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, from + "->" + to);
750                }
751            }
752        }
753        if (rest > 0) {
754            if (fread(buffer, rest, 1, fromFile) == 0) {
755                switch (errno) {
756                    case EIO:
757                    case EINTR:
758                    case ENOMEM:
759                    case EOVERFLOW:
760                    case EROFS:
761
762                        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, from + "->" + to);
763                }
764            }
765
766            if (fwrite(buffer, rest, 1, toFile) == 0) {
767                switch (errno) {
768                    case EIO:
769                    case EINTR:
770                    case ENOMEM:
771                    case EOVERFLOW:
772                    case EROFS:
773
774                        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, from + "->" + to);
775                }
776            }
777        }
778
779        if (fclose(fromFile) != 0)
780            dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, from + "->" + to);
781
782        if (fclose(toFile) != 0)
783            dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, from + "->" + to);
784    }
785}
786
787//-------------------------------------------------------------------
788
789void
790filesystem::copyDir(const dodo::string &from,
791                    const dodo::string &a_to,
792                    bool             force)
793{
794    dodo::string to = a_to;
795
796    {
797        char temp[PATH_MAXLEN];
798
799        strcpy(temp, to.data());
800        char *bname = ::basename(temp);
801        if (strcmp(bname, "..") == 0 || strcmp(bname, ".") == 0 || a_to[a_to.size() - 1] == '/')
802            to = bname + dodo::string("/") + basename((char *)from.data());
803    }
804
805    struct stat stFrom, stTo;
806
807    if (::lstat(from.data(), &stFrom) == -1)
808        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPYDIR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, from);
809
810    if (::lstat(to.data(), &stTo) == -1) {
811        if (errno != ENOENT)
812            dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPYDIR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, to);
813    } else if (force)
814        filesystem::rm(to, force);
815    else
816        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPYDIR, exception::ERRNO_LIBDODO, FILESYSTEMEX_WRONGFILENAME, TOOLSFILESYSTEMEX_WRONGFILENAME_STR, __LINE__, __FILE__, to);
817
818    if (!S_ISDIR(stFrom.st_mode))
819        filesystem::copy(from, to, force);
820    else {
821        if (::mkdir(to.data(), stFrom.st_mode) == -1)
822            dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPYDIR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, to);
823
824        dodo::string attachedFrom, attachedTo;
825
826        DIR *directory = opendir(from.data());
827        if (directory == NULL) {
828            if (errno == ENOENT)
829                return ;
830            else
831                dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPYDIR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, from);
832        }
833
834        dirent *dd;
835
836        while ((dd = readdir(directory)) != NULL) {
837            if ((strcmp(dd->d_name, ".") == 0) || (strcmp(dd->d_name, "..") == 0))
838                continue;
839
840            attachedTo = dodo::string(to + "/" + dd->d_name);
841            attachedFrom = dodo::string(from + "/" + dd->d_name);
842
843            filesystem::copyDir(attachedFrom, attachedTo, force);
844        }
845
846        if (closedir(directory) == -1)
847            dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX_COPYDIR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, from);
848    }
849}
850
851//-------------------------------------------------------------------
852
853bool
854filesystem::exists(const dodo::string &path)
855{
856    struct stat st;
857
858    if (::lstat(path.data(), &st) == 0)
859        return true;
860
861    return false;
862}
863
864//-------------------------------------------------------------------
865
866void
867filesystem::appendToFile(const dodo::string &path,
868                         const dodo::string &content)
869{
870    _writeToFile(path, content, "a+");
871}
872
873//-------------------------------------------------------------------
874
875void
876filesystem::appendToFile(const dodo::string      &path,
877                         const dodoStringArray &content)
878{
879    _writeToFile(path, content, "a+");
880}
881
882//-------------------------------------------------------------------
883
884void
885filesystem::writeToFile(const dodo::string &path,
886                        const dodo::string &content)
887{
888    _writeToFile(path, content, "w+");
889}
890
891//-------------------------------------------------------------------
892
893void
894filesystem::writeToFile(const dodo::string      &path,
895                        const dodoStringArray &content)
896{
897    _writeToFile(path, content, "w+");
898}
899
900//-------------------------------------------------------------------
901
902void
903filesystem::_writeToFile(const dodo::string &path,
904                         const dodo::string &content,
905                         const char       *mode)
906{
907    FILE *file = fopen(path.data(), mode);
908    if (file == NULL)
909        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX__WRITETOFILE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
910
911    unsigned long size = content.size();
912    if (size > 0 && fwrite(content.data(), size, 1, file) != 1)
913        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX__WRITETOFILE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
914}
915
916//-------------------------------------------------------------------
917
918void
919filesystem::_writeToFile(const dodo::string      &path,
920                         const dodoStringArray &content,
921                         const char            *mode)
922{
923    FILE *file = fopen(path.data(), mode);
924    if (file == NULL)
925        dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX__WRITETOFILE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
926
927    dodoStringArray::const_iterator i = content.begin(), j = content.end();
928    for (; i != j; ++i) {
929        if (i->size() > 0 && fputs(i->data(), file) < 0) {
930            switch (errno) {
931                case EFBIG:
932                case EIO:
933                case EINTR:
934                case EBADF:
935                case EOVERFLOW:
936                case ENOSPC:
937                case EPIPE:
938                case ENOMEM:
939                case ENXIO:
940
941                    dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX__WRITETOFILE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
942            }
943        }
944
945        if (fputc('\n', file) < 0) {
946            switch (errno) {
947                case EFBIG:
948                case EIO:
949                case EINTR:
950                case EBADF:
951                case EOVERFLOW:
952                case ENOSPC:
953                case EPIPE:
954                case ENOMEM:
955                case ENXIO:
956
957                    dodo_throw exception::basic(exception::MODULE_TOOLSFILESYSTEM, FILESYSTEMEX__WRITETOFILE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
958            }
959        }
960    }
961}
962
963//-------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.