blob: 15d6092155e7ee969fc6e23ac7d7a2076b8c47e2 [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>
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}