Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / fs-extra / lib / copy / ncp.js
1 // imported from ncp (this is temporary, will rewrite)
2
3 var fs = require('graceful-fs')
4 var path = require('path')
5 var utimes = require('../util/utimes')
6
7 function ncp (source, dest, options, callback) {
8   if (!callback) {
9     callback = options
10     options = {}
11   }
12
13   var basePath = process.cwd()
14   var currentPath = path.resolve(basePath, source)
15   var targetPath = path.resolve(basePath, dest)
16
17   var filter = options.filter
18   var transform = options.transform
19   var clobber = options.clobber !== false
20   var dereference = options.dereference
21   var preserveTimestamps = options.preserveTimestamps === true
22
23   var errs = null
24
25   var started = 0
26   var finished = 0
27   var running = 0
28   // this is pretty useless now that we're using graceful-fs
29   // consider removing
30   var limit = options.limit || 512
31
32   startCopy(currentPath)
33
34   function startCopy (source) {
35     started++
36     if (filter) {
37       if (filter instanceof RegExp) {
38         if (!filter.test(source)) {
39           return doneOne(true)
40         }
41       } else if (typeof filter === 'function') {
42         if (!filter(source)) {
43           return doneOne(true)
44         }
45       }
46     }
47     return getStats(source)
48   }
49
50   function getStats (source) {
51     var stat = dereference ? fs.stat : fs.lstat
52     if (running >= limit) {
53       return setImmediate(function () {
54         getStats(source)
55       })
56     }
57     running++
58     stat(source, function (err, stats) {
59       if (err) return onError(err)
60
61       // We need to get the mode from the stats object and preserve it.
62       var item = {
63         name: source,
64         mode: stats.mode,
65         mtime: stats.mtime, // modified time
66         atime: stats.atime, // access time
67         stats: stats // temporary
68       }
69
70       if (stats.isDirectory()) {
71         return onDir(item)
72       } else if (stats.isFile() || stats.isCharacterDevice() || stats.isBlockDevice()) {
73         return onFile(item)
74       } else if (stats.isSymbolicLink()) {
75         // Symlinks don't really need to know about the mode.
76         return onLink(source)
77       }
78     })
79   }
80
81   function onFile (file) {
82     var target = file.name.replace(currentPath, targetPath)
83     isWritable(target, function (writable) {
84       if (writable) {
85         copyFile(file, target)
86       } else {
87         if (clobber) {
88           rmFile(target, function () {
89             copyFile(file, target)
90           })
91         } else {
92           doneOne()
93         }
94       }
95     })
96   }
97
98   function copyFile (file, target) {
99     var readStream = fs.createReadStream(file.name)
100     var writeStream = fs.createWriteStream(target, { mode: file.mode })
101
102     readStream.on('error', onError)
103     writeStream.on('error', onError)
104
105     if (transform) {
106       transform(readStream, writeStream, file)
107     } else {
108       writeStream.on('open', function () {
109         readStream.pipe(writeStream)
110       })
111     }
112
113     writeStream.once('finish', function () {
114       fs.chmod(target, file.mode, function (err) {
115         if (err) return onError(err)
116         if (preserveTimestamps) {
117           utimes.utimesMillis(target, file.atime, file.mtime, function (err) {
118             if (err) return onError(err)
119             return doneOne()
120           })
121         } else {
122           doneOne()
123         }
124       })
125     })
126   }
127
128   function rmFile (file, done) {
129     fs.unlink(file, function (err) {
130       if (err) return onError(err)
131       return done()
132     })
133   }
134
135   function onDir (dir) {
136     var target = dir.name.replace(currentPath, targetPath)
137     isWritable(target, function (writable) {
138       if (writable) {
139         return mkDir(dir, target)
140       }
141       copyDir(dir.name)
142     })
143   }
144
145   function mkDir (dir, target) {
146     fs.mkdir(target, dir.mode, function (err) {
147       if (err) return onError(err)
148       // despite setting mode in fs.mkdir, doesn't seem to work
149       // so we set it here.
150       fs.chmod(target, dir.mode, function (err) {
151         if (err) return onError(err)
152         copyDir(dir.name)
153       })
154     })
155   }
156
157   function copyDir (dir) {
158     fs.readdir(dir, function (err, items) {
159       if (err) return onError(err)
160       items.forEach(function (item) {
161         startCopy(path.join(dir, item))
162       })
163       return doneOne()
164     })
165   }
166
167   function onLink (link) {
168     var target = link.replace(currentPath, targetPath)
169     fs.readlink(link, function (err, resolvedPath) {
170       if (err) return onError(err)
171       checkLink(resolvedPath, target)
172     })
173   }
174
175   function checkLink (resolvedPath, target) {
176     if (dereference) {
177       resolvedPath = path.resolve(basePath, resolvedPath)
178     }
179     isWritable(target, function (writable) {
180       if (writable) {
181         return makeLink(resolvedPath, target)
182       }
183       fs.readlink(target, function (err, targetDest) {
184         if (err) return onError(err)
185
186         if (dereference) {
187           targetDest = path.resolve(basePath, targetDest)
188         }
189         if (targetDest === resolvedPath) {
190           return doneOne()
191         }
192         return rmFile(target, function () {
193           makeLink(resolvedPath, target)
194         })
195       })
196     })
197   }
198
199   function makeLink (linkPath, target) {
200     fs.symlink(linkPath, target, function (err) {
201       if (err) return onError(err)
202       return doneOne()
203     })
204   }
205
206   function isWritable (path, done) {
207     fs.lstat(path, function (err) {
208       if (err) {
209         if (err.code === 'ENOENT') return done(true)
210         return done(false)
211       }
212       return done(false)
213     })
214   }
215
216   function onError (err) {
217     if (options.stopOnError) {
218       return callback(err)
219     } else if (!errs && options.errs) {
220       errs = fs.createWriteStream(options.errs)
221     } else if (!errs) {
222       errs = []
223     }
224     if (typeof errs.write === 'undefined') {
225       errs.push(err)
226     } else {
227       errs.write(err.stack + '\n\n')
228     }
229     return doneOne()
230   }
231
232   function doneOne (skipped) {
233     if (!skipped) running--
234     finished++
235     if ((started === finished) && (running === 0)) {
236       if (callback !== undefined) {
237         return errs ? callback(errs) : callback(null)
238       }
239     }
240   }
241 }
242
243 module.exports = ncp