source: node_modules/touch/index.js@ 62b2964

finki-main main
Last change on this file since 62b2964 was 81bc7da, checked in by Klimentina Efremova <klimentina08642@…>, 3 months ago

Initial commit

  • Property mode set to 100644
File size: 4.9 KB
RevLine 
[81bc7da]1'use strict'
2
3const EE = require('events').EventEmitter
4const cons = require('constants')
5const fs = require('fs')
6
7module.exports = (f, options, cb) => {
8 if (typeof options === 'function')
9 cb = options, options = {}
10
11 const p = new Promise((res, rej) => {
12 new Touch(validOpts(options, f, null))
13 .on('done', res).on('error', rej)
14 })
15
16 return cb ? p.then(res => cb(null, res), cb) : p
17}
18
19module.exports.sync = module.exports.touchSync = (f, options) =>
20 (new TouchSync(validOpts(options, f, null)), undefined)
21
22module.exports.ftouch = (fd, options, cb) => {
23 if (typeof options === 'function')
24 cb = options, options = {}
25
26 const p = new Promise((res, rej) => {
27 new Touch(validOpts(options, null, fd))
28 .on('done', res).on('error', rej)
29 })
30
31 return cb ? p.then(res => cb(null, res), cb) : p
32}
33
34module.exports.ftouchSync = (fd, opt) =>
35 (new TouchSync(validOpts(opt, null, fd)), undefined)
36
37const validOpts = (options, path, fd) => {
38 options = Object.create(options || {})
39 options.fd = fd
40 options.path = path
41
42 // {mtime: true}, {ctime: true}
43 // If set to something else, then treat as epoch ms value
44 const now = new Date(options.time || Date.now()).getTime() / 1000
45 if (!options.atime && !options.mtime)
46 options.atime = options.mtime = now
47 else {
48 if (true === options.atime)
49 options.atime = now
50
51 if (true === options.mtime)
52 options.mtime = now
53 }
54
55 let oflags = 0
56 if (!options.force)
57 oflags = oflags | cons.O_RDWR
58
59 if (!options.nocreate)
60 oflags = oflags | cons.O_CREAT
61
62 options.oflags = oflags
63 return options
64}
65
66class Touch extends EE {
67 constructor (options) {
68 super(options)
69 this.fd = options.fd
70 this.path = options.path
71 this.atime = options.atime
72 this.mtime = options.mtime
73 this.ref = options.ref
74 this.nocreate = !!options.nocreate
75 this.force = !!options.force
76 this.closeAfter = options.closeAfter
77 this.oflags = options.oflags
78 this.options = options
79
80 if (typeof this.fd !== 'number') {
81 this.closeAfter = true
82 this.open()
83 } else
84 this.onopen(null, this.fd)
85 }
86
87 emit (ev, data) {
88 // we only emit when either done or erroring
89 // in both cases, need to close
90 this.close()
91 return super.emit(ev, data)
92 }
93
94 close () {
95 if (typeof this.fd === 'number' && this.closeAfter)
96 fs.close(this.fd, () => {})
97 }
98
99 open () {
100 fs.open(this.path, this.oflags, (er, fd) => this.onopen(er, fd))
101 }
102
103 onopen (er, fd) {
104 if (er) {
105 if (er.code === 'EISDIR')
106 this.onopen(null, null)
107 else if (er.code === 'ENOENT' && this.nocreate)
108 this.emit('done')
109 else
110 this.emit('error', er)
111 } else {
112 this.fd = fd
113 if (this.ref)
114 this.statref()
115 else if (!this.atime || !this.mtime)
116 this.fstat()
117 else
118 this.futimes()
119 }
120 }
121
122 statref () {
123 fs.stat(this.ref, (er, st) => {
124 if (er)
125 this.emit('error', er)
126 else
127 this.onstatref(st)
128 })
129 }
130
131 onstatref (st) {
132 this.atime = this.atime && st.atime.getTime()/1000
133 this.mtime = this.mtime && st.mtime.getTime()/1000
134 if (!this.atime || !this.mtime)
135 this.fstat()
136 else
137 this.futimes()
138 }
139
140 fstat () {
141 const stat = this.fd ? 'fstat' : 'stat'
142 const target = this.fd || this.path
143 fs[stat](target, (er, st) => {
144 if (er)
145 this.emit('error', er)
146 else
147 this.onfstat(st)
148 })
149 }
150
151 onfstat (st) {
152 if (typeof this.atime !== 'number')
153 this.atime = st.atime.getTime()/1000
154
155 if (typeof this.mtime !== 'number')
156 this.mtime = st.mtime.getTime()/1000
157
158 this.futimes()
159 }
160
161 futimes () {
162 const utimes = this.fd ? 'futimes' : 'utimes'
163 const target = this.fd || this.path
164 fs[utimes](target, ''+this.atime, ''+this.mtime, er => {
165 if (er)
166 this.emit('error', er)
167 else
168 this.emit('done')
169 })
170 }
171}
172
173class TouchSync extends Touch {
174 open () {
175 try {
176 this.onopen(null, fs.openSync(this.path, this.oflags))
177 } catch (er) {
178 this.onopen(er)
179 }
180 }
181
182 statref () {
183 let threw = true
184 try {
185 this.onstatref(fs.statSync(this.ref))
186 threw = false
187 } finally {
188 if (threw)
189 this.close()
190 }
191 }
192
193 fstat () {
194 let threw = true
195 const stat = this.fd ? 'fstatSync' : 'statSync'
196 const target = this.fd || this.path
197 try {
198 this.onfstat(fs[stat](target))
199 threw = false
200 } finally {
201 if (threw)
202 this.close()
203 }
204 }
205
206 futimes () {
207 let threw = true
208 const utimes = this.fd ? 'futimesSync' : 'utimesSync'
209 const target = this.fd || this.path
210 try {
211 fs[utimes](target, this.atime, this.mtime)
212 threw = false
213 } finally {
214 if (threw)
215 this.close()
216 }
217 this.emit('done')
218 }
219
220 close () {
221 if (typeof this.fd === 'number' && this.closeAfter)
222 try { fs.closeSync(this.fd) } catch (er) {}
223 }
224}
Note: See TracBrowser for help on using the repository browser.