touch.js
4.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
var fs = require("fs")
, cons = require("constants")
module.exports = touch
touch.touchSync = touch.sync = function (f, options) {
return touch(f, options)
}
touch.ftouch = ftouch
touch.ftouchSync = function (fd, options) {
return ftouch(fd, options)
}
function validOpts (options) {
options = Object.create(options || {})
// {mtime: true}, {ctime: true}
// If set to something else, then treat as epoch ms value
var now = new Date(options.time || Date.now())
if (!options.atime && !options.mtime) {
options.atime = options.mtime = now
} else if (true === options.atime) {
options.atime = now
} else if (true === options.mtime) {
options.mtime = now
}
var oflags = 0
if (!options.force) {
oflags = oflags | cons.O_RDWR
}
if (!options.nocreate) {
oflags = oflags | cons.O_CREAT
}
options.oflags = oflags
return options
}
function optionsRef (then, arg, options, cb) {
if (!options.ref) return then(arg, options, cb)
return cb
? fs.stat(options.ref, optionsRefcb(then, arg, options, cb))
: optionsRefcb(then, arg, options)(null, fs.statSync(options.ref))
}
function optionsRefcb (then, arg, options, cb) { return function (er, s) {
if (er) {
er.path = er.file = options.ref
return cb(er)
}
options.atime = options.atime && s.atime.getTime()
options.mtime = options.mtime && s.mtime.getTime()
// so we don't keep doing this.
options.ref = null
return then(arg, options, cb)
}}
function touch (f, options, cb) {
if (typeof options === "function") cb = options, options = null
options = validOpts(options)
return optionsRef(touch_, f, validOpts(options), cb)
}
function touch_ (f, options, cb) {
return openThenF(f, options, cb)
}
function openThenF (f, options, cb) {
options.closeAfter = true
return cb
? fs.open(f, options.oflags, openThenFcb(options, cb))
: openThenFcb(options)(null, fs.openSync(f, options.oflags))
}
function openThenFcb (options, cb) { return function (er, fd) {
if (er) {
if (fd && options.closeAfter) fs.close(fd, function () {})
return cb(er)
}
return ftouch(fd, options, cb)
}}
function ftouch (fd, options, cb) {
if (typeof options === "function") cb = options, options = null
return optionsRef(ftouch_, fd, validOpts(options), cb)
}
function ftouch_ (fd, options, cb) {
// still not set. leave as what the file already has.
return fstatThenFutimes(fd, options, cb)
}
function fstatThenFutimes (fd, options, cb) {
if (options.atime && options.mtime) return thenFutimes(fd, options, cb)
return cb
? fs.fstat(fd, fstatThenFutimescb(fd, options, cb))
: fstatThenFutimescb(fd, options)(null, fs.fstatSync(fd))
}
function fstatThenFutimescb (fd, options, cb) { return function (er, s) {
if (er) {
if (options.closeAfter) fs.close(fd, function () {})
return cb(er)
}
options.atime = options.atime || s.atime.getTime()
options.mtime = options.mtime || s.mtime.getTime()
return thenFutimes(fd, options, cb)
}}
function thenFutimes (fd, options, cb) {
if (typeof options.atime === "object") {
options.atime = options.atime.getTime()
}
if (typeof options.mtime === "object") {
options.mtime = options.mtime.getTime()
}
var a = parseInt(options.atime / 1000, 10)
, m = parseInt(options.mtime / 1000, 10)
return cb
? fs.futimes(fd, a, m, thenFutimescb(fd, options, cb))
: thenFutimescb(fd, options)(null, fs.futimesSync(fd, a, m))
}
function thenFutimescb (fd, options, cb) { return function (er, res) {
if (er) {
if (options.closeAfter) fs.close(fd, function () {})
return cb(er)
}
return finish(fd, options, res, cb)
}}
function finish (fd, options, res, cb) {
return options.closeAfter ? finishClose(fd, options, res, cb)
: cb ? cb(null, res)
: res
}
function finishClose (fd, options, res, cb) {
return cb
? fs.close(fd, finishClosecb(res, options, cb))
: finishClosecb(res, options)(null, fs.closeSync(fd))
}
function finishClosecb (res, options, cb) { return function (er) {
if (er) return cb(er)
options.closeAfter = null
return finish(null, options, res, cb)
}}