lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Wed, Sep 26, 2018 at 05:25:39PM -0700, Paul K wrote:
> 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))