bug-gawk
[Top][All Lists]
Advanced

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

Re: [bug-gawk] in-place edit request


From: Andrew J. Schorr
Subject: Re: [bug-gawk] in-place edit request
Date: Wed, 26 Dec 2012 13:47:43 -0500
User-agent: Mutt/1.5.21 (2010-09-15)

On Wed, Dec 26, 2012 at 10:47:47AM -0500, Andrew J. Schorr wrote:
> The inplace_end function could then use the rename system call to avoid
> problems with filenames.  Of course, this assumes that rename works on all
> platforms; is rename portable?  The extension can also take more care to
> preserve file permissions, and possibly use mkstemp to make sure the temporary
> file has a unique name.  In the sed code, they use unlink to remove
> the temporary file if the rename call fails.  Is that desirable?
> It seems as if "unlink" may not work on VMS, since it's implemented in
> vms/vms_misc.c using "delete".  Then again, "unlink" is already used
> in the bundled fileop and rwarray extensions...

Also, the perl approach is quite different than sed.  Looking at an strace of
perl with -i, it first opens the input file, and then immediately renames (if a
backup is desired) or unlinks the original file and then opens the new file
with the same name.  The gawk BEGINFILE rule can also work this way, since
BEGINFILE is called after the file has been opened.  This avoids the need for
mkstemp.  It is more aggressive, but simpler.

An strace of perl -p -i.bak -e 's/foo/bar/;' /tmp/testfile:

open("/tmp/testfile", O_RDONLY)         = 3
ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 
0x7fff783e3e28) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR)                   = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=17, ...}) = 0
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
rename("/tmp/testfile", "/tmp/testfile.bak") = 0
open("/tmp/testfile", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4
ioctl(4, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 
0x7fff783e3e28) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(4, 0, SEEK_CUR)                   = 0
fstat(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fcntl(4, F_SETFD, FD_CLOEXEC)           = 0
fstat(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fchmod(4, 0100644)                      = 0
read(3, "is foo replaced?\n", 8192)     = 17
read(3, "", 8192)                       = 0
write(4, "is bar replaced?\n", 17)      = 17
close(4)                                = 0
close(3)                                = 0

And without a backup:

open("/tmp/testfile", O_RDONLY)         = 3
ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 
0x7fff05267508) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR)                   = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=17, ...}) = 0
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
unlink("/tmp/testfile")                 = 0
open("/tmp/testfile", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4
ioctl(4, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 
0x7fff05267508) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(4, 0, SEEK_CUR)                   = 0
fstat(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fcntl(4, F_SETFD, FD_CLOEXEC)           = 0
fstat(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fchmod(4, 0100644)                      = 0
read(3, "is foo replaced?\n", 8192)     = 17
read(3, "", 8192)                       = 0
write(4, "is bar replaced?\n", 17)      = 17
close(4)                                = 0
close(3)                                = 0

The danger here is that the file could be lost if there is a fatal error and no
backup is being used.  Is it worth the additional complexity of the sed
approach to avoid that risk?  I am assuming that none of our platforms would
remove a file until the last open reference has been closed...

Regards,
Andy



reply via email to

[Prev in Thread] Current Thread [Next in Thread]