fs.cpp revision 4f85cc54b3347e00e32a07cae4fd5473987b71af
1#include "fs.h"
2#include "files.h"
3#include <unistd.h>
4#include <sys/types.h>
5#include <dirent.h>
6#include <string>
7#include <vector>
8#include <stdio.h>
9#include <string.h>
10#include <errno.h>
11#include <sys/stat.h>
12#include <unistd.h>
13#include <host/CopyFile.h>
14
15using namespace std;
16
17static bool
18is_dir(const string& path)
19{
20    int err;
21    struct stat st;
22    err = stat(path.c_str(), &st);
23    return err != 0 || S_ISDIR(st.st_mode);
24}
25
26static int
27remove_file(const string& path)
28{
29    int err = unlink(path.c_str());
30    if (err != 0) {
31        fprintf(stderr, "error deleting file %s (%s)\n", path.c_str(),
32                strerror(errno));
33        return errno;
34    }
35    return 0;
36}
37
38int
39remove_recursively(const string& path)
40{
41    int err;
42
43    if (is_dir(path)) {
44        DIR *d = opendir(path.c_str());
45        if (d == NULL) {
46            fprintf(stderr, "error getting directory contents %s (%s)\n",
47                    path.c_str(), strerror(errno));
48            return errno;
49        }
50
51        vector<string> files;
52        vector<string> dirs;
53
54        struct dirent *ent;
55        while (NULL != (ent = readdir(d))) {
56            if (0 == strcmp(".", ent->d_name)
57                    || 0 == strcmp("..", ent->d_name)) {
58                continue;
59            }
60            string full = path;
61            full += '/';
62            full += ent->d_name;
63#ifdef HAVE_DIRENT_D_TYPE
64            bool is_directory = (ent->d_type == DT_DIR);
65#else
66	    	// If dirent.d_type is missing, then use stat instead
67			struct stat stat_buf;
68			stat(full.c_str(), &stat_buf);
69			bool is_directory = S_ISDIR(stat_buf.st_mode);
70#endif
71            if (is_directory) {
72                dirs.push_back(full);
73            } else {
74                files.push_back(full);
75            }
76        }
77        closedir(d);
78
79        for (vector<string>::iterator it=files.begin(); it!=files.end(); it++) {
80            err = remove_file(*it);
81            if (err != 0) {
82                return err;
83            }
84        }
85
86        for (vector<string>::iterator it=dirs.begin(); it!=dirs.end(); it++) {
87            err = remove_recursively(*it);
88            if (err != 0) {
89                return err;
90            }
91        }
92
93        err = rmdir(path.c_str());
94        if (err != 0) {
95            fprintf(stderr, "error deleting directory %s (%s)\n", path.c_str(),
96                    strerror(errno));
97            return errno;
98        }
99        return 0;
100    } else {
101        return remove_file(path);
102    }
103}
104
105int
106mkdir_recursively(const string& path)
107{
108    int err;
109    size_t pos = 0;
110    while (true) {
111        pos = path.find('/', pos);
112        string p = path.substr(0, pos);
113        struct stat st;
114        err = stat(p.c_str(), &st);
115        if (err != 0) {
116            err = mkdir(p.c_str(), 0770);
117            if (err != 0) {
118                fprintf(stderr, "can't create directory %s (%s)\n",
119                        path.c_str(), strerror(errno));
120                return errno;
121            }
122        }
123        else if (!S_ISDIR(st.st_mode)) {
124            fprintf(stderr, "can't create directory %s because %s is a file.\n",
125                        path.c_str(), p.c_str());
126            return 1;
127        }
128        pos++;
129        if (p == path) {
130            return 0;
131        }
132    }
133}
134
135int
136copy_file(const string& src, const string& dst)
137{
138    int err;
139
140    err = copyFile(src.c_str(), dst.c_str(),
141                    COPY_NO_DEREFERENCE | COPY_FORCE | COPY_PERMISSIONS);
142    return err;
143}
144