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