blob: 00f44c2c6f195dfc0f550db74d83bc2e5df04b57 [file] [log] [blame]
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001#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>
The Android Open Source Project4f85cc52009-01-09 17:50:54 -08009#include <string.h>
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -070010#include <errno.h>
11#include <sys/stat.h>
12#include <unistd.h>
Alexey Zaytsev8ae3ad52008-10-22 02:02:30 +040013#include <string.h>
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -070014#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}