Discussion:
Function to truncate a file
Paul K
2018-09-27 00:25:39 UTC
Permalink
I'd like to come back to Daurnimator's suggestion to add a file
truncation function to Lua
(http://lua-users.org/lists/lua-l/2011-12/msg00111.html).

I know Luiz responded "truncating to zero length is the same as
opening for writing, except for dates", but it's beneficial in many
cases to write to the same file, as it preserves its attributes,
metadata, permissions, etc.

Paul.
William Ahern
2018-09-27 03:51:55 UTC
Permalink
Post by Paul K
I'd like to come back to Daurnimator's suggestion to add a file
truncation function to Lua
(http://lua-users.org/lists/lua-l/2011-12/msg00111.html).
I know Luiz responded "truncating to zero length is the same as
opening for writing, except for dates", but it's beneficial in many
cases to write to the same file, as it preserves its attributes,
metadata, permissions, etc.
Paul.
At least on macOS there's no difference between truncate+0 and fopen:

inode atime mtime ctime
creat 8597642368 20:39:57 20:39:57 20:39:57
truncate 8597642368 20:39:57 20:39:59 20:39:59
fopen 8597642368 20:39:57 20:40:01 20:40:01

Perhaps truncate behaves differently on different POSIX systems or Windows
chsize behaves differently than POSIX truncate. But in either case there's
no consistency so it's not something you can depend on. Perhaps Luiz was
mistaken or being intentionally vague because he knew there was some
difference but wouldn't remember

FWIW, here's my test code using Lua 5.3:

local unix = require"unix"

local function stat_and_print(path, test)
local st = assert(unix.stat(path))
print(test,
st.ino,
os.date("%H:%M:%S", st.atime // 1),
os.date("%H:%M:%S", st.mtime // 1),
os.date("%H:%M:%S", st.ctime // 1))
end

-- basically the same as fopen(path, "w")
local function creat(path, mode)
local oflag = unix.O_CREAT | unix.O_TRUNC | unix.O_WRONLY
local fd, why, errno = unix.open(path, oflag, mode)
if not fd then return false, why, errno end
unix.close(fd)
return true
end

local path = os.tmpname()
print(" ", "inode ", "atime ", "mtime ", "ctime ")

do
assert(creat(path, tonumber("666", 8)))
stat_and_print(path, "creat ")
end

unix.sleep(2)

do
assert(unix.truncate(path))
stat_and_print(path, "truncate")
end

unix.sleep(2)

do
local fh = assert(io.open(path, "w"))
stat_and_print(path, "fopen ")
fh:close()
end

assert(os.remove(path))
Luiz Henrique de Figueiredo
2018-09-27 11:25:21 UTC
Permalink
Perhaps Luiz was mistaken or being intentionally vague
I think I meant that io.open(path, "w") might potentially imply in
removing the file and creating a new one.

OTOH, the man page for fopen in both macOS and Linux say

w Truncate file to zero length or create text file for writing.

That's exactly what the C99 standard says too.

Loading...