diff --git a/lib/luvit/fs.lua b/lib/luvit/fs.lua index d78917ccf..9d4a139f3 100644 --- a/lib/luvit/fs.lua +++ b/lib/luvit/fs.lua @@ -33,7 +33,6 @@ local sizes = { Rename = 2, Fsync = 1, Fdatasync = 1, - Ftruncate = 2, Sendfile = 4, Chmod = 2, Utime = 3, @@ -177,6 +176,43 @@ function fs.appendFileSync(path, data) fs.closeSync(fd) end +function fs.ftruncate(fd, len, callback) + if callback == nil then + callback = len + len = nil + end + native.fsFtruncate(fd, len or 0, callback or default) +end + +function fs.ftruncateSync(fd, len) + return native.fsFtruncate(fd, len or 0) +end + +function fs.truncate(path, len, callback) + if callback == nil then + callback = len + len = nil + end + fs.open(path, 'w', function(err, fd) + if err then return callback(err) end + native.fsFtruncate(fd, len or 0, function(err) + fs.close(fd, function(err2) + (callback or default)(err or err2) + end) + end) + end) +end + +function fs.truncateSync(path, len) + local fd = fs.openSync(path, 'w') + local ok, err + ok, err = pcall(native.fsFtruncate, fd, len or 0) + if not ok then + return err + end + fs.closeSync(fd) +end + local CHUNK_SIZE = 65536 local read_options = { diff --git a/tests/test-fs-truncate.lua b/tests/test-fs-truncate.lua new file mode 100644 index 000000000..7dcb1e12b --- /dev/null +++ b/tests/test-fs-truncate.lua @@ -0,0 +1,133 @@ +--[[ + +Copyright 2012 The Luvit Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License") +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS-IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +--]] + +require("helper") + +local FS = require('fs') +local Path = require('path') +local Buffer = require('buffer').Buffer +local string = require('string') + +local filename = Path.join(__dirname, 'tmp', 'truncate-file.txt') +local data = string.rep('x', 1024 * 16) + +local stat + +-- truncateSync +FS.writeFileSync(filename, data) +stat = FS.statSync(filename) +assert(stat.size == 1024 * 16) + +FS.truncateSync(filename, 1024) +stat = FS.statSync(filename) +assert(stat.size == 1024) + +FS.truncateSync(filename) +stat = FS.statSync(filename) +assert(stat.size == 0) + +-- ftruncateSync +FS.writeFileSync(filename, data) +local fd = FS.openSync(filename, 'a') + +stat = FS.statSync(filename) +assert(stat.size == 1024 * 16) + +FS.ftruncateSync(fd, 1024) +stat = FS.statSync(filename) +assert(stat.size == 1024) + +FS.ftruncateSync(fd) +stat = FS.statSync(filename) +assert(stat.size == 0) + +FS.closeSync(fd) + +function testTruncate(cb) + FS.writeFile(filename, data, function(er) + if er then return cb(er) end + FS.stat(filename, function(er, stat) + if er then return cb(er) end + assert(stat.size == 1024 * 16) + + FS.truncate(filename, 1024, function(er) + if er then return cb(er) end + FS.stat(filename, function(er, stat) + if er then return cb(er) end + assert(stat.size == 1024) + + FS.truncate(filename, function(er) + if er then return cb(er) end + FS.stat(filename, function(er, stat) + if er then return cb(er) end + assert(stat.size == 0) + cb() + end) + end) + end) + end) + end) + end) +end + + +function testFtruncate(cb) + FS.writeFile(filename, data, function(er) + if er then return cb(er) end + FS.stat(filename, function(er, stat) + if er then return cb(er) end + assert(stat.size == 1024 * 16) + + FS.open(filename, 'w', function(er, fd) + if er then return cb(er) end + FS.ftruncate(fd, 1024, function(er) + if er then return cb(er) end + FS.stat(filename, function(er, stat) + if er then return cb(er) end + assert(stat.size == 1024) + + FS.ftruncate(fd, function(er) + if er then return cb(er) end + FS.stat(filename, function(er, stat) + if er then return cb(er) end + assert(stat.size == 0) + FS.close(fd, cb) + end) + end) + end) + end) + end) + end) + end) +end + +-- async tests +local success = 0 +testTruncate(function(er) + if er then return er end + success = success + 1 + testFtruncate(function(er) + if er then return er end + success = success + 1 + end) +end) + +process:on('exit', function() + assert(success == 2) + p('ok') +end)