blob: 022bd8c0f8f65be958d85a47d5cee0b74ba511a9 [file] [log] [blame]
The Android Open Source Project88b60792009-03-03 19:28:42 -08001#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}