1 | var common = require('./common');
|
2 | var fs = require('fs');
|
3 |
|
4 | common.register('rm', _rm, {
|
5 | cmdOptions: {
|
6 | 'f': 'force',
|
7 | 'r': 'recursive',
|
8 | 'R': 'recursive',
|
9 | },
|
10 | });
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 | function rmdirSyncRecursive(dir, force, fromSymlink) {
|
21 | var files;
|
22 |
|
23 | files = fs.readdirSync(dir);
|
24 |
|
25 |
|
26 | for (var i = 0; i < files.length; i++) {
|
27 | var file = dir + '/' + files[i];
|
28 | var currFile = common.statNoFollowLinks(file);
|
29 |
|
30 | if (currFile.isDirectory()) {
|
31 | rmdirSyncRecursive(file, force);
|
32 | } else {
|
33 | if (force || isWriteable(file)) {
|
34 | try {
|
35 | common.unlinkSync(file);
|
36 | } catch (e) {
|
37 |
|
38 | common.error('could not remove file (code ' + e.code + '): ' + file, {
|
39 | continue: true,
|
40 | });
|
41 | }
|
42 | }
|
43 | }
|
44 | }
|
45 |
|
46 |
|
47 |
|
48 | if (fromSymlink) return;
|
49 |
|
50 |
|
51 |
|
52 |
|
53 | var result;
|
54 | try {
|
55 |
|
56 | var start = Date.now();
|
57 |
|
58 |
|
59 | for (;;) {
|
60 | try {
|
61 | result = fs.rmdirSync(dir);
|
62 | if (fs.existsSync(dir)) throw { code: 'EAGAIN' };
|
63 | break;
|
64 | } catch (er) {
|
65 |
|
66 |
|
67 | if (process.platform === 'win32' && (er.code === 'ENOTEMPTY' || er.code === 'EBUSY' || er.code === 'EPERM' || er.code === 'EAGAIN')) {
|
68 | if (Date.now() - start > 1000) throw er;
|
69 | } else if (er.code === 'ENOENT') {
|
70 |
|
71 | break;
|
72 | } else {
|
73 | throw er;
|
74 | }
|
75 | }
|
76 | }
|
77 | } catch (e) {
|
78 | common.error('could not remove directory (code ' + e.code + '): ' + dir, { continue: true });
|
79 | }
|
80 |
|
81 | return result;
|
82 | }
|
83 |
|
84 |
|
85 |
|
86 | function isWriteable(file) {
|
87 | var writePermission = true;
|
88 | try {
|
89 | var __fd = fs.openSync(file, 'a');
|
90 | fs.closeSync(__fd);
|
91 | } catch (e) {
|
92 | writePermission = false;
|
93 | }
|
94 |
|
95 | return writePermission;
|
96 | }
|
97 |
|
98 | function handleFile(file, options) {
|
99 | if (options.force || isWriteable(file)) {
|
100 |
|
101 | common.unlinkSync(file);
|
102 | } else {
|
103 | common.error('permission denied: ' + file, { continue: true });
|
104 | }
|
105 | }
|
106 |
|
107 | function handleDirectory(file, options) {
|
108 | if (options.recursive) {
|
109 |
|
110 | rmdirSyncRecursive(file, options.force);
|
111 | } else {
|
112 | common.error('path is a directory', { continue: true });
|
113 | }
|
114 | }
|
115 |
|
116 | function handleSymbolicLink(file, options) {
|
117 | var stats;
|
118 | try {
|
119 | stats = common.statFollowLinks(file);
|
120 | } catch (e) {
|
121 |
|
122 | common.unlinkSync(file);
|
123 | return;
|
124 | }
|
125 |
|
126 | if (stats.isFile()) {
|
127 | common.unlinkSync(file);
|
128 | } else if (stats.isDirectory()) {
|
129 | if (file[file.length - 1] === '/') {
|
130 |
|
131 | if (options.recursive) {
|
132 |
|
133 | var fromSymlink = true;
|
134 | rmdirSyncRecursive(file, options.force, fromSymlink);
|
135 | } else {
|
136 | common.error('path is a directory', { continue: true });
|
137 | }
|
138 | } else {
|
139 |
|
140 | common.unlinkSync(file);
|
141 | }
|
142 | }
|
143 | }
|
144 |
|
145 | function handleFIFO(file) {
|
146 | common.unlinkSync(file);
|
147 | }
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 | function _rm(options, files) {
|
168 | if (!files) common.error('no paths given');
|
169 |
|
170 |
|
171 | files = [].slice.call(arguments, 1);
|
172 |
|
173 | files.forEach(function (file) {
|
174 | var lstats;
|
175 | try {
|
176 | var filepath = (file[file.length - 1] === '/')
|
177 | ? file.slice(0, -1)
|
178 | : file;
|
179 | lstats = common.statNoFollowLinks(filepath);
|
180 | } catch (e) {
|
181 |
|
182 | if (!options.force) {
|
183 | common.error('no such file or directory: ' + file, { continue: true });
|
184 | }
|
185 | return;
|
186 | }
|
187 |
|
188 |
|
189 | if (lstats.isFile()) {
|
190 | handleFile(file, options);
|
191 | } else if (lstats.isDirectory()) {
|
192 | handleDirectory(file, options);
|
193 | } else if (lstats.isSymbolicLink()) {
|
194 | handleSymbolicLink(file, options);
|
195 | } else if (lstats.isFIFO()) {
|
196 | handleFIFO(file);
|
197 | }
|
198 | });
|
199 | return '';
|
200 | }
|
201 | module.exports = _rm;
|