touch.js 4.1 KB

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