Initial commit
[yaffs-website] / node_modules / graceful-fs / polyfills.js
1 var fs = require('./fs.js')
2 var constants = require('constants')
3
4 var origCwd = process.cwd
5 var cwd = null
6 process.cwd = function() {
7   if (!cwd)
8     cwd = origCwd.call(process)
9   return cwd
10 }
11 var chdir = process.chdir
12 process.chdir = function(d) {
13   cwd = null
14   chdir.call(process, d)
15 }
16
17 // (re-)implement some things that are known busted or missing.
18
19 // lchmod, broken prior to 0.6.2
20 // back-port the fix here.
21 if (constants.hasOwnProperty('O_SYMLINK') &&
22     process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
23   fs.lchmod = function (path, mode, callback) {
24     callback = callback || noop
25     fs.open( path
26            , constants.O_WRONLY | constants.O_SYMLINK
27            , mode
28            , function (err, fd) {
29       if (err) {
30         callback(err)
31         return
32       }
33       // prefer to return the chmod error, if one occurs,
34       // but still try to close, and report closing errors if they occur.
35       fs.fchmod(fd, mode, function (err) {
36         fs.close(fd, function(err2) {
37           callback(err || err2)
38         })
39       })
40     })
41   }
42
43   fs.lchmodSync = function (path, mode) {
44     var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode)
45
46     // prefer to return the chmod error, if one occurs,
47     // but still try to close, and report closing errors if they occur.
48     var err, err2
49     try {
50       var ret = fs.fchmodSync(fd, mode)
51     } catch (er) {
52       err = er
53     }
54     try {
55       fs.closeSync(fd)
56     } catch (er) {
57       err2 = er
58     }
59     if (err || err2) throw (err || err2)
60     return ret
61   }
62 }
63
64
65 // lutimes implementation, or no-op
66 if (!fs.lutimes) {
67   if (constants.hasOwnProperty("O_SYMLINK")) {
68     fs.lutimes = function (path, at, mt, cb) {
69       fs.open(path, constants.O_SYMLINK, function (er, fd) {
70         cb = cb || noop
71         if (er) return cb(er)
72         fs.futimes(fd, at, mt, function (er) {
73           fs.close(fd, function (er2) {
74             return cb(er || er2)
75           })
76         })
77       })
78     }
79
80     fs.lutimesSync = function (path, at, mt) {
81       var fd = fs.openSync(path, constants.O_SYMLINK)
82         , err
83         , err2
84         , ret
85
86       try {
87         var ret = fs.futimesSync(fd, at, mt)
88       } catch (er) {
89         err = er
90       }
91       try {
92         fs.closeSync(fd)
93       } catch (er) {
94         err2 = er
95       }
96       if (err || err2) throw (err || err2)
97       return ret
98     }
99
100   } else if (fs.utimensat && constants.hasOwnProperty("AT_SYMLINK_NOFOLLOW")) {
101     // maybe utimensat will be bound soonish?
102     fs.lutimes = function (path, at, mt, cb) {
103       fs.utimensat(path, at, mt, constants.AT_SYMLINK_NOFOLLOW, cb)
104     }
105
106     fs.lutimesSync = function (path, at, mt) {
107       return fs.utimensatSync(path, at, mt, constants.AT_SYMLINK_NOFOLLOW)
108     }
109
110   } else {
111     fs.lutimes = function (_a, _b, _c, cb) { process.nextTick(cb) }
112     fs.lutimesSync = function () {}
113   }
114 }
115
116
117 // https://github.com/isaacs/node-graceful-fs/issues/4
118 // Chown should not fail on einval or eperm if non-root.
119 // It should not fail on enosys ever, as this just indicates
120 // that a fs doesn't support the intended operation.
121
122 fs.chown = chownFix(fs.chown)
123 fs.fchown = chownFix(fs.fchown)
124 fs.lchown = chownFix(fs.lchown)
125
126 fs.chmod = chownFix(fs.chmod)
127 fs.fchmod = chownFix(fs.fchmod)
128 fs.lchmod = chownFix(fs.lchmod)
129
130 fs.chownSync = chownFixSync(fs.chownSync)
131 fs.fchownSync = chownFixSync(fs.fchownSync)
132 fs.lchownSync = chownFixSync(fs.lchownSync)
133
134 fs.chmodSync = chownFix(fs.chmodSync)
135 fs.fchmodSync = chownFix(fs.fchmodSync)
136 fs.lchmodSync = chownFix(fs.lchmodSync)
137
138 function chownFix (orig) {
139   if (!orig) return orig
140   return function (target, uid, gid, cb) {
141     return orig.call(fs, target, uid, gid, function (er, res) {
142       if (chownErOk(er)) er = null
143       cb(er, res)
144     })
145   }
146 }
147
148 function chownFixSync (orig) {
149   if (!orig) return orig
150   return function (target, uid, gid) {
151     try {
152       return orig.call(fs, target, uid, gid)
153     } catch (er) {
154       if (!chownErOk(er)) throw er
155     }
156   }
157 }
158
159 // ENOSYS means that the fs doesn't support the op. Just ignore
160 // that, because it doesn't matter.
161 //
162 // if there's no getuid, or if getuid() is something other
163 // than 0, and the error is EINVAL or EPERM, then just ignore
164 // it.
165 //
166 // This specific case is a silent failure in cp, install, tar,
167 // and most other unix tools that manage permissions.
168 //
169 // When running as root, or if other types of errors are
170 // encountered, then it's strict.
171 function chownErOk (er) {
172   if (!er)
173     return true
174
175   if (er.code === "ENOSYS")
176     return true
177
178   var nonroot = !process.getuid || process.getuid() !== 0
179   if (nonroot) {
180     if (er.code === "EINVAL" || er.code === "EPERM")
181       return true
182   }
183
184   return false
185 }
186
187
188 // if lchmod/lchown do not exist, then make them no-ops
189 if (!fs.lchmod) {
190   fs.lchmod = function (path, mode, cb) {
191     process.nextTick(cb)
192   }
193   fs.lchmodSync = function () {}
194 }
195 if (!fs.lchown) {
196   fs.lchown = function (path, uid, gid, cb) {
197     process.nextTick(cb)
198   }
199   fs.lchownSync = function () {}
200 }
201
202
203
204 // on Windows, A/V software can lock the directory, causing this
205 // to fail with an EACCES or EPERM if the directory contains newly
206 // created files.  Try again on failure, for up to 1 second.
207 if (process.platform === "win32") {
208   var rename_ = fs.rename
209   fs.rename = function rename (from, to, cb) {
210     var start = Date.now()
211     rename_(from, to, function CB (er) {
212       if (er
213           && (er.code === "EACCES" || er.code === "EPERM")
214           && Date.now() - start < 1000) {
215         return rename_(from, to, CB)
216       }
217       if(cb) cb(er)
218     })
219   }
220 }
221
222
223 // if read() returns EAGAIN, then just try it again.
224 var read = fs.read
225 fs.read = function (fd, buffer, offset, length, position, callback_) {
226   var callback
227   if (callback_ && typeof callback_ === 'function') {
228     var eagCounter = 0
229     callback = function (er, _, __) {
230       if (er && er.code === 'EAGAIN' && eagCounter < 10) {
231         eagCounter ++
232         return read.call(fs, fd, buffer, offset, length, position, callback)
233       }
234       callback_.apply(this, arguments)
235     }
236   }
237   return read.call(fs, fd, buffer, offset, length, position, callback)
238 }
239
240 var readSync = fs.readSync
241 fs.readSync = function (fd, buffer, offset, length, position) {
242   var eagCounter = 0
243   while (true) {
244     try {
245       return readSync.call(fs, fd, buffer, offset, length, position)
246     } catch (er) {
247       if (er.code === 'EAGAIN' && eagCounter < 10) {
248         eagCounter ++
249         continue
250       }
251       throw er
252     }
253   }
254 }
255