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